Skip to content

Instantly share code, notes, and snippets.

@a1xon
Created December 18, 2021 07:03
Show Gist options
  • Save a1xon/9eef7a77822e70c7e094fe39cc3915bd to your computer and use it in GitHub Desktop.
Save a1xon/9eef7a77822e70c7e094fe39cc3915bd to your computer and use it in GitHub Desktop.
Queue Manager to handle n async requests
const EventEmitter = require('events');
const { randomUUID } = require('crypto');
class AsyncQueueManager {
constructor(maxSimultaneousCalls = 1) {
this.maxSimultaneousCalls = maxSimultaneousCalls;
this.currentSimultaneousCalls = 0;
this.queue = [];
this.eventEmitter = new EventEmitter();
}
enqueue(prop) {
const id = randomUUID();
this.queue.push(() => this.call(id, prop));
const wrapperPromise = new Promise((resolve, reject) => {
this.eventEmitter.once(id, (type, result) => {
setImmediate(() => {
if (type) {
resolve(result);
} else {
reject(result);
}
});
});
});
this.dequeue();
return wrapperPromise;
}
async dequeue() {
if (this.queue.length >= 1 &&
this.currentSimultaneousCalls < this.maxSimultaneousCalls) {
this.currentSimultaneousCalls++;
await this.queue.shift()();
this.currentSimultaneousCalls--;
this.dequeue()
}
}
async call(id, prop) {
/// prop may hold url etc.
try {
/// any async function goes here -->
await new Promise(r => setTimeout(r, 1000));
/// return result of async function via event emitter -->
this.eventEmitter.emit(id, true, `RESULT ${prop}`)
} catch (err) {
/// false for rejecting promise
this.eventEmitter.emit(id, false, err)
}
/// call return only for internal queue handling
}
}
const asyncQueueManager = new AsyncQueueManager();
const start = async () => {
for (let i = 0; i < 10; i++) {
asyncQueueManager.enqueue(`prop-${i}`).then((result) => {
console.log(result);
});
}
}
start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment