JavaScript task queue

Simple FIFO task queue with limited concurrency

Here's Queue, a small utility function to queue and run tasks with limited concurrency.

const Queue = (concurrency) => {
    var running = 0;
    const tasks = [];

    return async (task) => {
        tasks.push(task);
        if (running >= concurrency) return;

        ++running;
        while (tasks.length) {
            try {
                await tasks.shift()();
            } catch(err) {
                console.error(err);
            }
        }
        --running;
    }
}

You enqueue a task by passing it to the function returned by Queue.

// Create the queue with a concurrency limit
const concurrency = 4
const enqueue = Queue(concurrency);

// In this case, each task is an async upload function...
const upload = async (file) => {...};

// ... and each task uploads a file
const files = [...];
files.forEach((file) => {
    enqueue(async () => upload(file));
});

If there is available concurrency, the task will run [almost] immediately. Otherwise, it will wait until enough tasks ahead of it have completed for it to run within the concurrency limit.

Use case

A use for this is part of a file uploader that allows arbitrary numbers of uploads. Although browsers limit the number of connections, they also limit how many requests are queued: Chrome can throw net::ERR_INSUFFICIENT_RESOURCES if you attempt to queue too many. To avoid this, you can queue the uploads up front.

Features

  • Can add tasks at any point after queue creation
  • No recursion
  • No polling
  • Small API
  • Small amount of code
  • Leverages async/await syntax: no handling of promises or callbacks, either internally or in client code

That's it!