Concurrency limit
- Node.js course
- Intermediate
- Lesson 49/116
- 5 min
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
// Write a mapLimit(items, limit, fn) function
// Process in parallel with limit workers
// write hereSample solution
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
while (i < items.____) { const idx = i; i++; results[idx] = await fn(items[idx]); }
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?
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.