Update 2023/08/03, 10:44: Modified my code to make clear the for loop could actually run for hours
I have an use case where I'd like to run multiple promises simultaneously, but resolve every promise in the order it was pushed into the queue. I came up with the solution below, but I'm not very happy with the approach. Any suggestions for improvements?
class PromiseQueue {
    #queue = [];
    enqueue(promise) {
        return new Promise((resolve) => {
            this.#queue.push({
                promise: promise(),
                resolve
            });
            
            if (this.#queue.length == 1) this.#dequeue();
        });
    }
    
    #dequeue() {
        let item = this.#queue[0];
        if (!item) return;
        item.promise.then((val) => {
            item.resolve(val);
            this.#queue.shift();
            this.#dequeue();
        });
    }
}
Usage
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
function randomNumber(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}
async function* getSwaps() { 
// ....
}
async function run() {
    let queue = new PromiseQueue();
    let i = 0;
    // could run for hours
    for await (let logs of getSwaps() {
        let fn = async () => {
            await sleep(randomNumber(300, 1000));
            return i;
        }
        
        queue.enqueue(fn).then((val) => {
            console.log(val)
            // write data to database as soon as available
        });
        i++;
    }    
}
run();
 
    