Home > Software design >  JavaScript returning way too early
JavaScript returning way too early

Time:04-13

I am wanting a to call this to save a variable as an array by calling a function to create the array by key presses

moves = xenet().getDirections("3000");
console.log("Your moves were "   moves);

And the JavaScript works it just returns undefined and way to early so what am I doing wrong.

    getDirections: (duration) => {
    let moves = [];
    let on = true;
    if (on == true) {
        window.addEventListener('keydown', keyPress, true);
        console.log("Getting Directions");
        // Code Returns Right here
        function keyPress(e) {
            if (e.key == "w", e.key == "ArrowUp") {moves.push("Up")}
            if (e.key == "a", e.key == "ArrowLeft") {moves.push("Left")}
            if (e.key == "s", e.key == "ArrowDown") {moves.push("Down");}
            if (e.key == "d", e.key == "ArrowRight") {moves.push("Right");}
            console.log("Key pressed");
        }
        setTimeout(function() {
            on == false;
            window.removeEventListener("keydown", keyPress, true);
            console.log("Stopped getting directions");
            return moves; // I want the code to return the created array right here
        }, duration);
    }
    
}

CodePudding user response:

There are multiple issues here:

  1. At the call site, your duration is a string -- it should be a number
  2. You don't return anything from getDirections
  3. Even if you did try to return from getDirections, setTimeout is asynchronous, so the return wouldn't work as expected.
  4. You should use === for comparisons like this
  5. The OR operator is ||, not ,

Here's an updated, working version. It uses a "completion handler" which calls a function when the setTimeout is complete.

const getDirections = (duration, completion) => {
  let moves = [];
  function keyPress(e) {
    if (e.key === "w" || e.key === "ArrowUp") {moves.push("Up")}
    if (e.key === "a" || e.key === "ArrowLeft") {moves.push("Left")}
    if (e.key === "s" || e.key === "ArrowDown") {moves.push("Down");}
    if (e.key === "d" || e.key === "ArrowRight") {moves.push("Right");}
    console.log("Key pressed");
  }

    window.addEventListener('keydown', keyPress, true);
    console.log("Getting Directions");

    setTimeout(function() {
        window.removeEventListener("keydown", keyPress, true);
        console.log("Stopped getting directions");
        completion(moves); // I want the code to return the created array right here
    }, duration);
}

getDirections(10000, moves => console.log("Moves:",moves))

CodePudding user response:

setTimeout is an asynchronous function. You cannot return a value from an async function synchronously. The function executing the setTimeout (getDirections) will finish executing before the callback passed to setTimeout is called. To accomplish what you are trying to do, you need to use Promises or async/await.

For example:

async function getDirections(duration){
    let moves = [];
    let on = true;
    if (on == true) {
        window.addEventListener('keydown', keyPress, true);
        console.log("Getting Directions");
        function keyPress(e) {
            if (e.key == "w", e.key == "ArrowUp") {moves.push("Up")}
            if (e.key == "a", e.key == "ArrowLeft") {moves.push("Left")}
            if (e.key == "s", e.key == "ArrowDown") {moves.push("Down");}
            if (e.key == "d", e.key == "ArrowRight") {moves.push("Right");}
            console.log("Key pressed");
        }
      var promise = new Promise(function(resolve, reject) {
           window.setTimeout(function() {
                  on = false;
                  window.removeEventListener("keydown", keyPress, true);
                  console.log("Stopped getting directions");
                  resolve(moves);
              }, duration);
         });
         return promise;
    }    
}

async function getResult() {
  const result = await getDirections("3000");
  console.log("Your moves were "   result)
}

getResult();

  • Related