javascriptnode.jspromiseasync-awaitfor-await

for await of VS Promise.all


Is there any difference between this:

const promises = await Promise.all(items.map(e => somethingAsync(e)));
for (const res of promises) {
  // do some calculations
}

And this ?

for await (const res of items.map(e => somethingAsync(e))) {
  // do some calculations
}

I know that in the first snippet, all the promises are fired at the same time but I'm not sure about the second. Does the for loop wait for the first iteration to be done to call the next promise ? Or are all the promises fired at the same time and the inside of the loop acts like a callback for them ?


Solution

  • Yes, they absolutely are different. for await is supposed to be used with asynchronous iterators, not with arrays of pre-existing promises.

    Just to make clear,

    for await (const res of items.map(e => somethingAsync(e))) …
    

    works the same as

    const promises = items.map(e => somethingAsync(e));
    for await (const res of promises) …
    

    or

    const promises = [somethingAsync(items[0]), somethingAsync(items[1]), …];
    for await (const res of promises) …
    

    The somethingAsync calls are happening immediately, all at once, before anything is awaited. Then, they are awaited one after another, which is definitely a problem if any one of them gets rejected: it will cause an unhandled promise rejection error. Using Promise.all is the only viable choice to deal with the array of promises:

    for (const res of await Promise.all(promises)) …
    

    See Waiting for more than one concurrent await operation and Any difference between await Promise.all() and multiple await? for details.