Skip to content

Commit e1fe436

Browse files
committed
add promise limiter in javascript
1 parent fec9e1f commit e1fe436

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

javascript/pLimit.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// pLimit.js
2+
// Minimal promise concurrency limiter (like p-limit). Queue tasks, run at most N at once.
3+
4+
/**
5+
* @typedef {() => Promise<any>} Task
6+
*/
7+
8+
/**
9+
* Create a concurrency limiter.
10+
* @param {number} concurrency - number of tasks to run simultaneously (>=1)
11+
* @returns {{
12+
* (fn: (...args:any[])=>Promise<any>|any, ...args:any[]): Promise<any>,
13+
* activeCount: () => number,
14+
* pendingCount: () => number,
15+
* clearQueue: () => void
16+
* }}
17+
*/
18+
export function pLimit(concurrency = 4) {
19+
if (!Number.isInteger(concurrency) || concurrency < 1) {
20+
throw new Error("concurrency must be an integer >= 1");
21+
}
22+
23+
/** @type {Task[]} */
24+
const queue = [];
25+
let active = 0;
26+
27+
const next = () => {
28+
if (active >= concurrency) return;
29+
const task = queue.shift();
30+
if (!task) return;
31+
active++;
32+
task().finally(() => {
33+
active--;
34+
next();
35+
});
36+
};
37+
38+
const run = (fn, ...args) => new Promise((resolve, reject) => {
39+
const task = async () => {
40+
try {
41+
resolve(await fn(...args));
42+
} catch (e) {
43+
reject(e);
44+
}
45+
};
46+
queue.push(task);
47+
// Try to start tasks ASAP (microtask ensures consistent ordering)
48+
queue.length && queue.length <= concurrency ? Promise.resolve().then(next) : next();
49+
});
50+
51+
run.activeCount = () => active;
52+
run.pendingCount = () => queue.length;
53+
run.clearQueue = () => { queue.length = 0; };
54+
55+
return run;
56+
}
57+
58+
// // Example usage:
59+
// const limit = pLimit(2);
60+
// const wait = ms => new Promise(r => setTimeout(r, ms));
61+
// await Promise.all([1,2,3,4,5].map(n => limit(async () => { await wait(100*n); return n; })));

0 commit comments

Comments
 (0)