13
votes

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?

4
It starts resolving when you create it, not when you await itJonas Wilms

4 Answers

7
votes

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();
2
votes

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();
2
votes

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.

0
votes

The run function is in synchronous order e.g. the code takes it step by step:

  1. call func1() and wait until there is a reply.
  2. call func2() and wait until there is a reply.
  3. log var1.
  4. log var2.

So the last 2 steps will only run when the call to func2() has completed the promise e.g. the data after the timeout. So it will wait the full 5 seconds until logging both var1 and var2.

The other way is fairly different 1. call func1() and wait until there is a reply. 2. log var1. 3. call func2() and wait until there is a reply. 4. log var2.

Step 2 will wait until step one has returned data e.g. after the 100ms and then will move on to doing the same for step 3 and 4.