/** * Allow promises to be queued up and executed in order. */ export class PromiseQueue { private queue: any[] = []; private locked: boolean = false; /** Add new promise to queue */ add(p: () => Promise, delay?: number) { this._add(p, false, delay); } /** Add new promise to the from of the queue */ addToBeginning(p: () => Promise, delay?: number) { this._add(p, true, delay); } /** Clear the queue and reset state. */ clearQueue() { this.queue = []; } private delay = (ms: number) => () => new Promise(resolve => setTimeout(resolve, ms)); _add = (p: () => Promise, beginning: boolean = false, delay?: number) => { const newPromise = delay ? [p, this.delay(delay)] : [p]; beginning ? this.queue.unshift(newPromise) : this.queue.push(newPromise); if (!this.locked) { this.next(); } }; private next() { this.locked = true; const p = this.queue.shift(); const finished = () => { this.queue.length > 0 ? this.next() : (this.locked = false); }; Promise.all(p.map((v: any) => v())) .then(finished) .catch(finished); } }