Deep Clone Object
Create a fully independent copy of nested objects where modifying the clone never affects the…
Run async operations with a concurrency limit to prevent overwhelming servers and network resources.
class PromiseQueue {
constructor(concurrency = 3) {
this.concurrency = concurrency;
this.running = 0;
this.queue = [];
}
add(asyncFn) {
return new Promise((resolve, reject) => {
this.queue.push({ asyncFn, resolve, reject });
this.flush();
});
}
flush() {
while (this.running < this.concurrency && this.queue.length > 0) {
const { asyncFn, resolve, reject } = this.queue.shift();
this.running++;
asyncFn()
.then(resolve)
.catch(reject)
.finally(() => {
this.running--;
this.flush();
});
}
}
}
Let us trace what happens when you queue 5 API calls with a concurrency limit of 2:
add(task1) → running: 0 < 2 → START task1 → running: 1
add(task2) → running: 1 < 2 → START task2 → running: 2
add(task3) → running: 2 = 2 → QUEUED (position 1)
add(task4) → running: 2 = 2 → QUEUED (position 2)
add(task5) → running: 2 = 2 → QUEUED (position 3)
task1 completes → running: 1 → flush() → START task3 → running: 2
task2 completes → running: 1 → flush() → START task4 → running: 2
task3 completes → running: 1 → flush() → START task5 → running: 2
task4 completes → running: 1 → flush() → queue empty, done
task5 completes → running: 0 → flush() → queue empty, done
At no point did more than 2 tasks run simultaneously
The finally block is the engine. Every time a task completes — whether it succeeds or fails — it decrements the counter and calls flush() again. This creates a self-sustaining loop: finished tasks automatically pull new ones from the queue without any external orchestration.
Promise.all with 1000 URLs:
→ 1000 simultaneous HTTP connections
→ Server returns 429 (Too Many Requests)
→ Network adapter overwhelmed
→ Browser tab freezes
PromiseQueue with concurrency 5:
→ Max 5 connections at a time
→ Server handles the load
→ Results stream in steadily
→ UI stays responsive
// Upload images with max 3 concurrent uploads
const queue = new PromiseQueue(3);
const uploadResults = await Promise.all(
files.map(file =>
queue.add(() => uploadToServer(file))
)
);
// Fetch paginated API data without overwhelming the server
const queue = new PromiseQueue(5);
const pages = Array.from({ length: 50 }, (_, i) => i + 1);
const allData = await Promise.all(
pages.map(page =>
queue.add(() =>
fetch(`/api/records?page=${page}`)
.then(res => res.json())
)
)
);
Use this whenever you have many async operations that would overwhelm a resource if fired all at once. File uploads, API pagination, database batch operations, and web scraping are common cases. Set concurrency based on what the target can handle: 3 to 5 for external APIs, 10 to 20 for internal services, and 1 for operations that must run sequentially.