export class AsyncQueue { private items: T[] = []; private resolvers: ((value: T) => void)[] = []; push(item: T): void { if (this.resolvers.length > 0) { const resolve = this.resolvers.shift()!; resolve(item); } else { this.items.push(item); } } pushAll(items: Iterable): void { for (const item of items) { this.push(item); } } async pop(): Promise { if (this.items.length > 0) { return this.items.shift()!; } return new Promise((resolve) => { this.resolvers.push(resolve); }); } get length(): number { return this.items.length - this.resolvers.length; } }