export default class Queue { pendingItems: Array = []; nextItemResolver!: () => void; nextItem: Promise = new Promise( (done) => (this.nextItemResolver = done) ); put(item: ItemT): void { this.pendingItems.push(item); this.nextItemResolver(); this.nextItem = new Promise((done) => (this.nextItemResolver = done)); } get(): Promise { const item = this.pendingItems.shift(); if (item) { // return the next queued item immediately return Promise.resolve(item); } let resolver: (item: ItemT) => void; const nextItemPromise: Promise = new Promise( (done) => (resolver = done) ); this.nextItem.then(() => { resolver(this.pendingItems.shift() as ItemT); }); return nextItemPromise; } }