async-poolx
v1.0.0
Published
Tiny, zero-dependency async pool with concurrency control, cancellation, and retries
Maintainers
Readme
async-poolx 🏊♂️⚡
A tiny, zero-dependency async pool for JavaScript with concurrency control, cancellation, and retries.
Because Promise.all() shouldn’t feel like playing Jenga with your production server.
✨ Why async-poolx?
If you’ve ever had:
- 100+ async tasks
- a server yelling “rate limit exceeded”
- memory spikes
- or no clean way to cancel ongoing work
…then async-poolx is for you.
It lets you run async tasks in parallel, but responsibly.
🚀 Features
- ✅ Controlled concurrency (run only N tasks at once)
- ✅ Preserves input order in results
- ✅ Built-in cancellation via
AbortSignal - ✅ Optional retries with delay
- ✅ Progress callback
- ✅ Tiny, fast, zero dependencies
📦 Install
npm install async-poolx🔧 Basic Usage
import pool from 'async-poolx';
// or: const pool = require('async-poolx');
const items = [1, 2, 3, 4, 5];
const results = await pool(items, 2, async (item) => {
await new Promise(r => setTimeout(r, 100));
return item * 2;
});
console.log(results);
// → [2, 4, 6, 8, 10]🧠 How it works (in one sentence)
async-poolx runs at most N async tasks at a time, starts new ones as others finish, and resolves when everything is done.
🛠 API
pool(items, concurrency, handler, options?)
Parameters
itemsArray- List of inputs to process
concurrencynumber- Maximum number of tasks running in parallel
handler(item) => Promise<any>- Async function that processes one item
options(optional)
Options
signal — AbortController support
const controller = new AbortController();
pool(items, 3, handler, {
signal: controller.signal
});
// Cancel all pending work
controller.abort();onProgress — Progress callback
onProgress: (completed, total, result) => {
console.log(`${completed}/${total} done`);
}retry — Automatic retries
retry: {
attempts: 3,
delay: 200 // ms
}Retries a failed task up to attempts times with an optional delay.
📌 Real-world Use Cases
- 🌐 API calls (avoid rate limits)
- 📂 File processing
- 📊 Data pipelines
- 🧵 Background jobs
- 🛑 Abortable user actions
⚡ Performance
Example benchmark:
- 100 async tasks
- 10ms per task
- concurrency = 10
Expected runtime: ~100ms
Minimal overhead, maximum control.
❓ Why not Promise.all?
Because:
- It fires everything at once
- No concurrency control
- No cancellation
- No retries
- No mercy 😬
🧩 Philosophy
- Small API
- No magic
- No dependencies
- Easy to read, easy to extend
📝 A Note to Fellow Developers
This library exists because at some point someone wrote Promise.all(500Requests)
and the server immediately questioned all of its life choices.
async-poolx is intentionally:
- small enough to read in one sitting
- boring enough to trust
- flexible enough to extend
If you’re reading the source:
yes, it’s just promises, race, and a little discipline — no wizardry involved.
If you find a bug, have an idea, or think something can be simpler: open an issue or PR. Good async code should be shared, not copy-pasted forever.
Happy pooling 🏊♂️
— cinfinit
