Build a queue that processes async tasks with concurrency limit
class AsyncQueue {
constructor(concurrency = 1) {
this.concurrency = concurrency;
this.running = 0;
this.queue = [];
}
async add(fn) {
while (this.running >= this.concurrency) {
await new Promise(resolve => this.queue.push(resolve));
}
this.running++;
try {
return await fn();
} finally {
this.running--;
this.queue.shift()?.();
}
}
}class AsyncQueue {
constructor(concurrency = 2) {
this.concurrency = concurrency;
this.running = 0;
this.queue = [];
}
async add(fn) {
while (this.running >= this.concurrency) {
await new Promise(resolve => this.queue.push(resolve));
}
this.running++;
try {
return await fn();
} finally {
this.running--;
const next = this.queue.shift();
if (next) next();
}
}
}
// Usage
const queue = new AsyncQueue(2); // Max 2 concurrent tasks
const tasks = [1, 2, 3, 4, 5].map(n =>
() => fetch(`/api/item/${n}`)
);
const results = await Promise.all(
tasks.map(task => queue.add(task))
);class PriorityQueue extends AsyncQueue {
add(fn, priority = 0) {
return super.add(() => ({ fn, priority }));
}
}class RateLimitedQueue {
constructor(rateLimit, interval) {
this.queue = [];
this.rateLimit = rateLimit;
this.interval = interval;
this.count = 0;
}
async add(fn) {
if (this.count >= this.rateLimit) {
await new Promise(resolve =>
setTimeout(resolve, this.interval)
);
this.count = 0;
}
this.count++;
return fn();
}
}Avoid processing all promises at once for large datasets
// DON'T DO THIS with 1000s of URLs
const results = await Promise.all(
urls.map(url => fetch(url))
);✓ Works in all modern browsers (ES2017+)