export class AsyncQueue implements AsyncIterator, AsyncIterable { #queue: X[] = []; #done = false; #ready = Promise.withResolvers(); constructor(signal?: AbortSignal) { signal?.addEventListener('abort', () => this.close()); if (signal?.aborted) { this.close(); } } [Symbol.asyncIterator](): AsyncIterator { return this; } async next(): Promise> { while (!this.#done && !this.#queue.length) { await this.#ready.promise; this.#ready = Promise.withResolvers(); } return { value: (this.#queue.length ? this.#queue.shift() : undefined)!, done: this.#done }; } async throw(error?: Error): Promise> { this.#done = true; this.#ready.reject(error); return { value: undefined, done: this.#done }; } add(item: X): void { this.#queue.push(item); this.#ready.resolve(); } close(): void { this.#done = true; this.#ready.resolve(); } }