When is `await` resolved simultaneously?
Asked Answered
B

1

5

The MDN documentation for async function currently gives the following combined example of two ways to use await. I've reordered it just a bit for emphasis:

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}


async function add1(x) {
  const a = await resolveAfter2Seconds(20);
  const b = await resolveAfter2Seconds(30);
  return x + a + b;
}

async function add2(x) {
  const p_a = resolveAfter2Seconds(20);
  const p_b = resolveAfter2Seconds(30);
  return x + await p_a + await p_b;
}


add1(10).then(v => {
  console.log(v);  // prints 60 after 4 seconds.
});

add2(10).then(v => {
  console.log(v);  // prints 60 after 2 seconds.
});

This was a bit surprising to me. Why does

const a = await resolveAfter2Seconds(20);
const b = await resolveAfter2Seconds(30);
return x + a + b;

resolve the two promises sequentially, while

return x + await p_a + await p_b;

seemingly resolves the two promises simultaneously? Is this behavior specified for await specifically, or a natural consequence of something else?

Byyourleave answered 31/10, 2017 at 23:39 Comment(4)
Thanks, I'd like a reference with a bit more specific rules for this, though. E.g. obviously "line" is a simplification here, although perhaps it has to do with language-level statements?Byyourleave
A function with multiple await expressions in it will be suspended once at a time on each await expression until that Promise is settled, before unsuspending execution and moving onto the next await expression – not unlike the case we observe with generators and yield. Source: ponyfoo.com/articles/understanding-javascript-async-awaitPolypus
@Polypus Hmm, but then how do you explain the NOT "once at a time" behavior when more than one await statement appears within a single expression/statement/___?Byyourleave
await is sequential. In the second example both await are fired at the same time. in the first example one await is fired, async function paused until getting resolved and second async function fired then. Reference: exploringjs.com/es2016-es2017/…Polypus
C
7
async function add2(x) {
  const p_a = resolveAfter2Seconds(20);
  const p_b = resolveAfter2Seconds(30);
  return x + await p_a + await p_b;
}

In this statement p_a and p_b are started in parallel (i.e., as soon as you generate the promise), so when you await p_a and p_b they would appear parallel, not sequential.

To get the other functionality (await in series) you would need to:

return x + await resolveAfter2Seconds(20) + await resolveAfter2Seconds(30);
Chuffy answered 1/11, 2017 at 0:1 Comment(1)
Ah, makes perfect sense now :-) It has everything to do with when the evaluation of the async function call happens, rather than anything to do with the syntax/context of the await statements themselves. Thanks!Byyourleave

© 2022 - 2024 — McMap. All rights reserved.