Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are parallel awaits in JS/TS limited to Chrome only?

Experiencing what appears to be weird promise resolution behavior in JS/TS. Node LTS. It's completely possible that it comes down to whether the promise resolves to a value that is then read later on in the code, vs fire-and-forget (void response type). Hoping for experts to weigh in.

According to this Google dev blog post, you should be able to cut wait time in half by deferring your await call on two async/await functions.

Original post: https://web.dev/async-functions/#careful-avoid-going-too-sequential

However.. on node.js (both v16 and v18/lts) that logic doesn't work.

If we encapsulate their example in an async IIFE, we can demo it with this code:

(async () => {
  function wait(ms, value) {
    return new Promise(resolve => setTimeout(resolve, ms, value));
  }

  const t = 500
  const msg = 'done'
  const wait1 = wait(t, msg); // Start a 500ms timer asynchronously…
  const wait2 = wait(t, msg); // …meaning this timer happens in parallel.
  await wait1; // Wait 500ms for the first timer…
  await wait2; // …by which time this timer has already finished.
  console.log(wait1, wait2)
})()

Notice the values of wait1 and wait2 in the console.log ending statement.

console.log(wait1,wait2)
// Promise { 'done' } Promise { 'done' }

Why are wait1 and wait2 still unresolved promises if we called await on them?

Consider this additional logic, which doesn't make me feel better about the logic flow happening here. If we call await on those variables again in console.log, the promise is resolved...

console.log(await wait1, await wait2)
// done done

So by calling await on these variables again we finally get resolved promise values?

Is this a weird difference between Node and Chrome's implementation of V8, or is this the intended behavior when we're returning a resolved promise's value vs when we are only awaiting a function's execution with a void response?

like image 904
staysense_dev_1 Avatar asked Nov 28 '25 04:11

staysense_dev_1


1 Answers

Why are wait1 and wait2 still unresolved promises if we called await on them?

Promise objects don't stop being promise objects when they are fulfilled with a result. There's no magic going on, and the variables you have still hold the promises themselves no the results. An await expression does return the result value, but the statement await wait1; simply discards that result.

You would want to write

const wait1 = wait(500, 'done1');
const wait2 = wait(400, 'done2');
const res1 = await wait1;
const res2 = await wait2;
console.log(res1, res2); // instead of console.log(wait1, wait2)
//          ^^^^  ^^^^

or rather (much better)

const [res1, res2] = await Promise.all([wait1, wait2]);
console.log(res1, res2);
like image 172
Bergi Avatar answered Nov 29 '25 16:11

Bergi