Ad

Using Await Inline On Variable In Outer Scope

- 1 answer

(async function iife () {
  const numbers = [1, 2, 3, 4]
  let count = 0
  async function returnNumberAsync (number) {
    return new Promise(resolve => {
      setTimeout(() => resolve(number), 0)
    })
  }
  await Promise.all(numbers.map(async number => {
    count += await returnNumberAsync(number)
  }))
  console.log(count)
})()

This snippet logs 4 to the console, which is completely beyond me. As soon as I assign the promised value inside map to its own local variable …

const result = await returnNumberAsync(number)
count += result;

… it logs 10 like I'd expect. What's happening when I count += await …??

Ad

Answer

When you do count += await <expression>, the initial value of count to be added to the resolve value is saved before the await part is resolved. So

count += await returnNumberAsync(number)

is like

count = count + await returnNumberAsync(number)

as you can see:

(async function iife () {
  const numbers = [1, 2, 3, 4]
  let count = 0
  async function returnNumberAsync (number) {
    return new Promise(resolve => {
      setTimeout(() => resolve(number), 0)
    })
  }
  await Promise.all(numbers.map(async number => {
    count = count + await returnNumberAsync(number)
  }))
  console.log(count)
})()

In each of the 4 closures, count is seen to be 0 before the awaits resolve, so only in the final await microtask, where it resolves to

count += await returnNumberAsync(4)
// or
count = 0 + await returnNumberAsync(4)
// or
count = 4

does 4 get assigned to count. The fact that other numbers were assigned to count earlier is ignored. They did happen, but the assignment of the final iteration is all you see with the current code.

Ad
source: stackoverflow.com
Ad