Facebook Pixel

async/await in Loops in JavaScript

await in loops can be sequential or parallel. Here is how to use it correctly in each loop type.

async/await in Loops in JavaScript

Using await in loops is a common source of confusion. Here is how to do it correctly in each loop type.

for...of (Sequential)

for (const url of urls) { const data = await fetch(url); process(data); }

This is sequential: each fetch waits for the previous one. Good for dependent operations, slow for independent ones.

forEach (Does NOT Work)

// bad: forEach does not await urls.forEach(async (url) => { const data = await fetch(url); process(data); // runs in parallel, not sequential }); console.log("done"); // logs before any fetch completes

forEach does not await the async callback. The loop finishes immediately, and the fetches run in parallel in the background. This is usually not what you want.

map (Parallel with Promise.all)

const results = await Promise.all( urls.map((url) => fetch(url).then((r) => r.json())) ); results.forEach(process);

This is parallel: all fetches start at once. Good for independent operations.

while (Sequential)

let i = 0; while (i < urls.length) { const data = await fetch(urls[i]); process(data); i++; }

for (Sequential)

for (let i = 0; i < urls.length; i++) { const data = await fetch(urls[i]); process(data); }

Parallel with Concurrency Limit

async function parallelWithLimit(items, limit, fn) { const results = []; for (let i = 0; i < items.length; i += limit) { const batch = items.slice(i, i + limit); const batchResults = await Promise.all(batch.map(fn)); results.push(...batchResults); } return results; }

Process limit items at a time (e.g., 5 at a time) to avoid overwhelming the server.

Which to Use?

  • Sequential (dependent): for...of, while, for.
  • Parallel (independent): Promise.all with .map.
  • Parallel with limit: custom batching.
  • Never: forEach with await (it does not await).

The Takeaway

for...of supports sequential await. forEach does not await (avoid). Promise.all with .map is parallel. For concurrency limits, batch with Promise.all. Use sequential for dependent operations, parallel for independent, and never use forEach with await.

No. forEach does not await the async callback. The loop finishes immediately, and the async callbacks run in parallel in the background. This is usually not what you want. Use for...of for sequential await or Promise.all with map for parallel.

Use for...of: for (const url of urls) { const data = await fetch(url); process(data); }. Each iteration waits for the previous one. Use this for dependent operations.

Use Promise.all with map: const results = await Promise.all(urls.map(url => fetch(url))). All fetches start at once. Use this for independent operations (much faster than sequential).

Batch with Promise.all: process limit items at a time. for (let i = 0; i < items.length; i += limit) { await Promise.all(items.slice(i, i + limit).map(fn)); }. This avoids overwhelming the server.

for...of, while, and for loops support sequential await. forEach does NOT await the async callback. map returns an array of promises (use with Promise.all for parallel).

Ready to master React completely?

Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.