CodeBlanks Logo Icon CodeBlanks

Concurrency limit

Learn to limit parallel work with a concurrency limit.

Concurrency limit

Concurrency limit is a pattern used to cap the number of async jobs running at the same time. You build a pool: N workers pull jobs from a queue. Example: mapLimit(items, 2, fn) runs at most 2 jobs at once.

The pattern is: an i counter, a results array and N worker functions. Each worker takes the next job with while (i < items.length), processes it with await fn(items[idx]) and writes the result to results[idx]. All workers are awaited with Promise.all(workers). This is used to avoid sending hundreds of API requests at once; the server does not reject. The limit parameter sets the worker count; a typical value is 2–10.

The worker pattern

A worker is an async function that pulls jobs from the queue with a while loop. Example: async function worker() { while (i < items.length) { const idx = i; i++; results[idx] = await fn(items[idx]); } }.

The const idx = i; i++; pattern is critical: it copies i into a local idx first, then increments. Two workers never take the same idx. The results[idx] assignment puts the result in the right slot; even if running order differs, results follow the original order. N workers start: for (let w = 0; w < limit; w++) workers.push(worker()). Then await Promise.all(workers) waits for all. This is the standard way to keep parallelism bounded.

Practice Write the mapLimit function

Write async function mapLimit(items, limit, fn): const results = []; let i = 0;. Add async function worker() with while (i < items.length) { const idx = i; i++; results[idx] = await fn(items[idx]); }. Start N workers with for (let w = 0; w < limit; w++) workers.push(worker()). await Promise.all(workers); return results;. main() is ready: console.log("Results: " + results.join(",")).

Starter code

index.js
// Write a mapLimit(items, limit, fn) function
// Process in parallel with limit workers
// write here

Sample solution

index.js
async function mapLimit(items, limit, fn) {
  const results = [];
  let i = 0;
  async function worker() {
    while (i < items.length) {
      const idx = i;
      i++;
      results[idx] = await fn(items[idx]);
    }
  }
  const workers = [];
  for (let w = 0; w < limit; w++) {
    workers.push(worker());
  }
  await Promise.all(workers);
  return results;
}

async function main() {
  const items = [1, 2, 3];
  const fn = async function(x) { return x * 10; };
  const results = await mapLimit(items, 2, fn);
  console.log("Results: " + results.join(","));
}

main();

Expected output

Sonuçlar: 10,20,30

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Match each piece to its role

Term Meaning
limit Worker count
worker Pulls a job from the queue
Promise.all Awaits all workers
results[idx] Writes result by index

2 Complete the worker while condition

Question
while (i < items.____) { const idx = i; i++; results[idx] = await fn(items[idx]); }
Answer
while (i < items.length) { const idx = i; i++; results[idx] = await fn(items[idx]); }

Explanation: items.length gives the array's size.

3 Why use mapLimit?

index.js
const results = await mapLimit(items, 2, fn)
  • To limit how many tasks run at the same time Correct answer
  • To catch errors
  • To filter the array
  • To sort the array

Explanation: mapLimit caps the number of jobs running at once.

All lessons in Intermediate