Back to Home
Async

How to Create an Async Queue

Build a queue that processes async tasks with concurrency limit

Quick Answer (2024 ES6+ Way)

javascript
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()?.();
    }
  }
}

Live Example

javascript
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))
);

Common Variations

With Priority
javascript
class PriorityQueue extends AsyncQueue {
  add(fn, priority = 0) {
    return super.add(() => ({ fn, priority }));
  }
}
Rate Limited
javascript
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();
  }
}

❌ Don't Do This (Outdated Way)

Avoid processing all promises at once for large datasets

javascript
// DON'T DO THIS with 1000s of URLs
const results = await Promise.all(
  urls.map(url => fetch(url))
);

Browser Support

Works in all modern browsers (ES2017+)

#async#queue#concurrency