export type WorkQueueProcessor = (job: T) => Promise; interface JobItem { job: T; resolvers: PromiseWithResolvers; } export class WorkQueue { #active: boolean = false; #queue: JobItem[] = []; #callback: WorkQueueProcessor; constructor(processor: WorkQueueProcessor) { this.#callback = processor; } submit(job: T) { const resolvers = Promise.withResolvers(); this.#queue.push({ job, resolvers }); this.#loop(); return resolvers.promise; } async #loop() { if (this.#active) { return; } const item = this.#queue.shift(); if (!item) { return; } this.#active = true; const { job, resolvers } = item; await this.#callback(job).then(resolvers.resolve, resolvers.reject); this.#active = false; await this.#loop(); } }