DEV3 Technologies home

DEV3 Developer Forum

Why does await inside forEach not wait in JavaScript?

JavaScript helpSolved0 views
dev3 ·

I have this code and 'done' prints before the items are saved:

items.forEach(async (item) => { await save(item); });
console.log('done');

How do I make it wait?

#javascript#async#await

0

1 reply

dev3 · Accepted answer

forEach ignores the return value of its callback. An async callback returns a promise, which forEach throws away, so nothing waits for it.

Sequential (one after another)

for (const item of items) {
  await save(item);
}
console.log('done');

Parallel (all at once)

await Promise.all(items.map((item) => save(item)));
console.log('done');

map returns an array of promises and Promise.all waits for all of them. If one rejects, Promise.all rejects immediately (the others keep running). Use Promise.allSettled to get every outcome:

const results = await Promise.allSettled(items.map(save));
const failed = results.filter((r) => r.status === 'rejected');

Limited concurrency

Firing 5000 requests at once can overload an API or database. Process in chunks:

for (let i = 0; i < items.length; i += 10) {
  await Promise.all(items.slice(i, i + 10).map(save));
}

or use a small pool library such as p-limit.

Which to choose

  • Order matters or each step depends on the last: for...of.
  • Independent work: Promise.all.
  • Same for filter, reduce and some: async callbacks always return truthy promises, so items.filter(async ...) keeps everything.

Pitfall: await only works inside an async function or a module top level (ES modules).

0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.