@monstermann/fn
Version:
A utility library for TypeScript.
65 lines (63 loc) • 1.49 kB
JavaScript
import { defer } from "./defer.js";
import { createQueue, dequeue, enqueue } from "./internals/queue.js";
//#region src/promise/queue.ts
/**
* `queue(options)`
*
* Creates a queue that limits concurrent execution of tasks.
*
* ```ts
* const taskQueue = queue({ concurrency: 2 });
* const taskQueue2 = queue(2); // shorthand
*
* const results = await Promise.all([
* // At most 2 fetch calls are executed at any time
* taskQueue.add(() => fetchData(1)),
* taskQueue.add(() => fetchData(2)),
* taskQueue.add(() => fetchData(3)),
* ]);
*
* // Wait for queue to become idle
*/
function queue(options) {
const concurrency = getConcurrency(options);
const queue$1 = createQueue();
let idle;
let running = 0;
function flush() {
while (running < concurrency) {
const next = dequeue(queue$1);
if (!next) break;
running++;
next();
}
if (!queue$1.size && running === 0) {
idle?.resolve();
idle = void 0;
}
}
function done() {
running--;
flush();
}
return {
add(fn) {
idle ??= defer();
const deferred = defer();
const result = deferred.promise.then(fn).finally(done);
enqueue(queue$1, deferred.resolve);
flush();
return result;
},
idle() {
return idle?.promise ?? Promise.resolve();
}
};
}
function getConcurrency(options) {
const base = typeof options === "number" ? options : options.concurrency;
if (!Number.isSafeInteger(base)) return Infinity;
return Math.max(base, 1);
}
//#endregion
export { queue };