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();