Solved

await inside forEach does not wait for anything

Asked by Arjun Rao · 751 views · 3 replies

Arjun Rao4 messages

I want to save some items and then log "all done":

items.forEach(async (item) => {
  await saveItem(item);
});
console.log("all done");

"all done" prints first, before any of the saves finish. I put await right there, so why is it not waiting?

3 replies

Kenji MoritaSolution

The await is waiting, but only inside each callback. forEach calls your async function, gets a promise back, and throws that promise away. It never waits on it, so the loop ends straight away and console.log runs.

Pick based on what you want.

One at a time, in order: use for...of, where await pauses the loop itself:

for (const item of items) {
  await saveItem(item);
}
console.log("all done");

All at once: map to promises and wait for all of them:

await Promise.all(items.map((item) => saveItem(item)));
console.log("all done");

The second is faster, but if any save rejects, Promise.all rejects straight away. The other saves keep running; you just stop waiting for them. Use Promise.allSettled if you need every result regardless.

Link
Daniela Rocha

Worth saying: "all at once" with 5,000 items means 5,000 requests at the same moment, and most APIs will rate-limit you for that. For big lists, process them in chunks of, say, 20 with Promise.all per chunk.

Link
Arjun Rao

That makes total sense now. for...of it is, since the saves have to happen in order anyway. Thanks both.

Link