import { defer, Deferred } from './defer.js'; export const createQueue = () => { const pendingQueue: Deferred[] = []; const resolvedQueue: Deferred[] = []; const requestQueue: Deferred[] = []; const push = (value: T): Deferred => { const task = defer(); pendingQueue.push(task); Promise.resolve(value) .then(task.resolve) .catch(task.reject) .finally(() => { pendingQueue.splice(pendingQueue.indexOf(task), 1); if (requestQueue.length > 0) { const request = requestQueue.shift(); request.resolve(task.promise); } else { resolvedQueue.push(task); } }); return task; }; const pull = (): Deferred => { if (resolvedQueue.length > 0) { return resolvedQueue.shift(); } const task = defer(); requestQueue.push(task); return task; }; return { push, pull, done(value: T) { push(value); return Promise.all( [...pendingQueue, ...resolvedQueue, ...requestQueue].map( (d) => d.promise, ), ); }, get size() { return pendingQueue.length + resolvedQueue.length + requestQueue.length; }, }; };