class PromiseQueue { constructor({ concurrency = 1 } = {}) { this.options = { concurrency }; this.running = 0; this.queue = []; this.idleCallbacks = []; } clear() { this.queue = []; } onIdle(callback) { this.idleCallbacks.push(callback); return () => { const index = this.idleCallbacks.indexOf(callback); if (index !== -1) { this.idleCallbacks.splice(index, 1); } }; } waitTillIdle() { return new Promise((resolve) => { if (this.running === 0) { resolve(); return; } const dispose = this.onIdle(() => { dispose(); resolve(); }); }); } add(callback) { return new Promise((resolve, reject) => { const runCallback = () => { this.running += 1; try { Promise.resolve(callback()).then((val) => { resolve(val); this.processNext(); }, (err) => { reject(err); this.processNext(); }); } catch (err) { reject(err); this.processNext(); } }; if (this.running >= this.options.concurrency) { this.queue.push(runCallback); } else { runCallback(); } }); } // Internal function, don't use processNext() { this.running -= 1; const callback = this.queue.shift(); if (callback) { callback(); } else if (this.running === 0) { this.idleCallbacks.forEach((item) => item()); } } } export { PromiseQueue };