Source: media/data/PromiseQueue.js

export { PromiseQueue }

/**
 * Class representing a promise queue.
 * Credits:
 * Markosyan. (2019, April 5). How to manage promises into dynamic queue with Vanilla JavaScript.
 * Medium. https://medium.com/@karenmarkosyan/how-to-manage-promises-into-dynamic-queue-with-vanilla-javascript-9d0d1f8d4df5 
 */
class PromiseQueue {
    /**
     * Create a queue.
     */
    constructor() {
        this.queue = [];
        this.pendingPromise = false;
    }

    /**
     * Add a function containing a promise to the queue.
     * @param {Function} promise - Callback function that returns a promise.
     * @returns Promise that resolves the outcome of the input promise when it is dequeued.
     */
    enqueue(promise) {
        return new Promise((resolve, reject) => {
            this.queue.push({
                promise,
                resolve,
                reject,
            });
            this._dequeue();
        });
    }

    /**
     * Remove and execute the next promise on the stack from the queue.
     * @returns true if successful else false.
     */
    _dequeue() {
        if (this.workingOnPromise) {
            return false;
        }
        const item = this.queue.shift();
        if (!item) {
            return false;
        }
        try {
            this.workingOnPromise = true;
            item.promise()
                .then((value) => {
                    this.workingOnPromise = false;
                    item.resolve(value);
                    this._dequeue();
                })
                .catch(err => {
                    this.workingOnPromise = false;
                    item.reject(err);
                    this._dequeue();
                })
        } catch (err) {
            this.workingOnPromise = false;
            item.reject(err);
            this._dequeue();
        }
        return true;
    }
}