Package Exports
- @henrygd/queue
- @henrygd/queue/async-storage
Readme
@henrygd/queue

Tiny async queue with concurrency control. Like p-limit
but smaller, faster, and easier.
Installation
npm install @henrygd/queue
Usage
Create a queue with the newQueue
function, then add promises / async functions to the queue with the add
method.
You can use queue.done()
to wait for the queue to be empty.
import { newQueue } from '@henrygd/queue'
// create a new queue with a concurrency of 2
const queue = newQueue(2)
const pokemon = ['ditto', 'hitmonlee', 'pidgeot', 'poliwhirl', 'golem', 'charizard']
for (const name of pokemon) {
queue.add(async () => {
const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`)
const json = await res.json()
console.log(`${json.name}: ${json.height * 10}cm | ${json.weight / 10}kg`)
})
}
console.log('running')
await queue.done()
console.log('done')
The return type is the same as the supplied promise, so you can use it as if you were using the supplied promise directly.
const res = await queue.add(() => fetch('https://pokeapi.co/api/v2/pokemon'))
console.log(res.ok, res.status, res.headers)
[!TIP] If you need support for Node's AsyncLocalStorage, import
@henrygd/queue/async-storage
instead.
Interface
// add adds a promise / async function to the queue
queue.add(() => Promise<T>): Promise<T>
// size returns the total number of promises in the queue
queue.size(): number
// active returns the number of promises currently running
queue.active(): number
// clear empties the queue (active promises are not cancelled)
queue.clear(): void
// done returns a promise that resolves when the queue is empty
queue.done(): Promise<void>
Similar libraries and benchmarks
Library | Version | Weekly downloads | Bundle size (bytes) |
---|---|---|---|
@henrygd/queue | 1.0.1 | only me :) | 342 |
p-limit | 5.0.0 | 118,953,973 | 1,763 |
queue | 7.0.0 | 4,259,101 | 2,840 |
promise-queue | 2.2.5 | 1,092,431 | 2,200 |
Browser benchmark
Each operation adds 1,000 async functions to the queue and waits for them to resolve. The function just increments a counter.
In reality, you may not be running so many jobs at once, and your jobs will take much longer to resolve. So performance will depend more on the jobs themselves.
This test was run on Chromium. Chrome / Edge / Opera are the same. Firefox is slower but differences are fairly similar. On Safari you need to uncheck "Run tests in parallel" to get accurate results, and queue
is a lot faster somehow.
You can run or tweak for yourself here: https://jsbm.dev/cnBxC9EQrjHhX
Bun benchmark
Same test as the browser benchmark, but uses 2,000 promises instead of 1,000.
Real world examples
henrygd/optimize
- Uses @henrygd/queue
to parallelize image optimization jobs.