Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this JavaScript async/await code not behave as expected?

I've tried reading guides and tutorials to async/await, but I can't seem to find this addressed anywhere.

Here is the code in question:

    var func1 = new Promise((resolve, reject) => {
      console.log("Func1");
      setTimeout(() => {
        resolve(10);
      }, 100);
    });
    
    var func2 = new Promise((resolve, reject) => {
      console.log("Func2");
      setTimeout(() => {
        resolve(20);
      }, 5000);
    })
    
    let run = async() => {
      let var1 = await func1;
      let var2 = await func2;
      console.log(var1);
      console.log(var2);
    }

    run();

We see "Func1" and "Func2" get printed immediately, one after the other. 5 seconds later, the timeout specified in func2, we get "10" and "20" printed. So far so good.

But if I change the last bit of code to this:

let run = async() => {
  let var1 = await func1;
  console.log(var1);
  let var2 = await func2;
  console.log(var2);
}

Then I see "Func1" immediately printed, but "Func2" as well, even though the console.log(var1) comes before it. After 100ms comes "10", then after 5 seconds comes "20".

From MDN:

The await expression causes async function execution to pause until a Promise is fulfilled or rejected, and to resume execution of the async function after fulfillment.

But it doesn't seem like this is what's happening. If it was, wouldn't we see "Func1", then "10", THEN func2 gets executed, thus printing "Func2" and 5 seconds later we get "20"? func1 should be executed, and once it is resolved (in 100 ms), console.log(var1) should fire. What am I missing here?

like image 670
HanifC Avatar asked Dec 13 '17 14:12

HanifC


3 Answers

await basically means enshure that the following value is available before continuing. The promise starts resolving when you create it, it does not matter when it is awaited.

like image 186
Jonas Wilms Avatar answered Nov 15 '22 17:11

Jonas Wilms


The reason for this is that you already ran your promise executors before. Promise executors are evaluated straight away when passed to the Promise constructor, so you'll get the following:

var func1 = new Promise((resolve, reject) => ...); // Logs "Func1"
var func2 = new Promise((resolve, reject) => ...); // Logs "Func2"

let run = async() => {
  let var1 = await func1;
  console.log(var1); // Logs 10
  let var2 = await func2;
  console.log(var2); // Logs 20
}

run();
like image 7
John Weisz Avatar answered Nov 15 '22 16:11

John Weisz


The main problem here is func1 and func2 are not functions; They are promises. Like Jonas W. says, promises will call their callback (resolve, reject) => immediately, and awaiting them just causes them to wait until they are resolved.

You can see your desired result here:

var func1 = () => {
   return new Promise((resolve, reject) => {
    console.log("Func1");
    setTimeout(() => {
      resolve(10);
    }, 100);
  });
}
        
var func2 = () => {
  return new Promise((resolve, reject) => {
    console.log("Func2");
    setTimeout(() => {
      resolve(20);
    }, 5000);
  });
}
        
let run = async() => {
  let var1 = await func1();
  let var2 = await func2();
  console.log(var1);
  console.log(var2);
}

run();
like image 2
ugh StackExchange Avatar answered Nov 15 '22 17:11

ugh StackExchange