UNPKG

@henrygd/queue

Version:

Tiny async queue with concurrency control. Like p-limit or fastq, but smaller and faster.

73 lines (72 loc) 1.58 kB
/** * This version of `@henrygd/queue` supports AsyncLocalStorage / AsyncResource. * * It should not be used in a web browser. * @module */ import { AsyncResource } from "async_hooks"; let Promize = Promise; let newQueue = (concurrency) => { let active = 0; let size = 0; let head; let tail; let resolveDonePromise; let donePromise; let queue; let afterRun = () => { active--; if (--size) { run(); } else { donePromise = resolveDonePromise?.(); } }; let run = () => { if (head && active < concurrency) { active++; let curHead = head; head = head.next; curHead.p().then( (v) => (curHead.res(v), afterRun()), (e) => (curHead.rej(e), afterRun()) ); } }; return queue = { add(p) { let node = { p: AsyncResource.bind(p) }; let promise = new Promize((res, rej) => { node.res = res; node.rej = rej; }); if (head) { tail = tail.next = node; } else { tail = head = node; } size++; run(); return promise; }, done: () => { if (!size) { return Promize.resolve(); } if (donePromise) { return donePromise; } return donePromise = new Promize((resolve) => resolveDonePromise = resolve); }, clear() { head = tail = null; size = active; }, active: () => active, size: () => size, all: (fns) => Promize.all(fns.map((fn) => queue.add(typeof fn === "function" ? fn : () => fn))) }; }; export { newQueue };