Ch. 1 · JavaScript

JavaScript Async Loops and Concurrency

JavaScript Async Loops and Concurrency. Learn the reasoning, a practical example, common mistakes and an interview exercise.

~2 min readintermediateupdated Oct 3, 2026

Async callbacks do not make forEach await returned promises. Choose sequential, parallel or bounded execution according to ordering and resource constraints.

Step-by-step walkthrough

Step 1: Choose required ordering

First decide whether operations may overlap and whether their completion order matters. Sequential execution is straightforward when each operation depends on the previous result. Independent work can overlap, but ordering of returned results and ordering of side effects are different concerns.

Step 2: Await the owned promises

For-of with await owns one operation at a time. Promise.all over map owns a set of promises and waits for the whole set. ForEach discards callback return values, so awaiting the forEach call does not await the asynchronous callback work.

Step 3: Bound resource use

Launching every operation can overwhelm connections or memory. Use a worker pool when the input is large, and define whether one failure stops scheduling or collects per-item outcomes. Already started work needs its own cancellation and cleanup policy.

Worked scenario

For-of with await serializes saves. Promise.all over map starts every save immediately and waits for completion.

async function saveSequentially(items, save) {
  const results = [];
  for (const item of items) results.push(await save(item));
  return results;
}
async function saveInParallel(items, save) {
  return Promise.all(items.map(item => save(item)));
}
// Both return results in input order; their start times differ.
JavaScript

Walk through the example

The sequential loop starts the next save only after the current save fulfills. The parallel version starts all saves during map and then waits. Promise.all preserves result positions even when operations complete out of order, but external side effects may occur in any order.

Common mistake

Promise.all rejection does not cancel started work; excessive parallel requests can hit rate limits.

Verify the behavior

Use controlled promises to record start times and resolve operations out of order. Verify sequential work has only one active operation. Test one rejection in parallel and observe that other started operations still continue unless the adapter supports explicit cancellation.

Interview exercise

Upload with three active requests.

Answer and reasoning

Use a worker pool taking the next item after settlement; collect outcomes and handle cancellation deliberately.

Follow-up discussion

Does async make CPU work parallel? No: it describes promise-based control flow, not automatic worker execution. Why can an async forEach test pass accidentally? Fast operations may finish before assertions by chance; the caller still lacks a promise representing their completion.

Continue learning

Compare the scenario with the JavaScript interview questions and test your understanding with the JavaScript MCQs. For terminology and implementation details, consult the reference material.

More in JavaScript

read ✓JavaScript · hard

JavaScript Async Iteration and Backpressure

Consume async generators with for await, propagate errors and pace a producer to a slow consumer without buffering the whole stream.

~3 min readread →
read ✓JavaScript · mid

JavaScript Date and Timezone Pitfalls

Parse and format dates without timezone surprises: zero-based months, date-only versus date-time parsing, and why UTC storage avoids drift.

~3 min readread →
esc