How to Control Promise Concurrency in JavaScript
Learn how to limit concurrent API calls in JavaScript using async queues and promise batching — a crucial skill for scalable frontend systems.
Advertisement
Question
You have 100 API calls to make, but you want to run only 5 at a time to avoid hitting rate limits.
How would you control the concurrency of async requests in JavaScript?
Explanation
When you use Promise.all, all promises run concurrently.
But if you call an API too many times simultaneously, you can trigger rate limits or browser connection limits.
A better pattern is to use a task queue or promise pool.
Example: Limited Concurrency with Async Queue
async function asyncPool(limit, tasks) {
const results = [];
const executing = new Set();
for (const task of tasks) {
const p = task().then((res) => {
executing.delete(p);
return res;
});
results.push(p);
executing.add(p);
if (executing.size >= limit) {
await Promise.race(executing);
}
}
return Promise.all(results);
}
Usage:
const urls = Array.from({ length: 100 }, (_, i) => `https://api.com/data/${i}`);
const tasks = urls.map((url) => () => fetch(url).then((r) => r.json()));
asyncPool(5, tasks).then(console.log);
Visualization
graph TD A[100 Tasks] -->|Limit 5| B[Run Batch 1] B --> C[Wait for One to Finish] C -->|Next Batch| D[Run Batch 2] D --> E[All Done ✅]
This ensures only 5 concurrent requests at a time.
Real-World Usage
- API integrations with rate-limits
- Uploading files in controlled batches
- Processing long-running tasks efficiently
Summary
Promise.all= runs everything at onceasyncPoolpattern = concurrency-safe- Use
Promise.race()to know when any async task finishes - Great for real-world apps with throttling or large data processing
Can Promise.all be used directly for concurrency control?
No, Promise.all triggers all promises at once. You need to batch or queue them manually.
Advertisement
Stay Updated
Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.
Advertisement