Skip to content

Instantly share code, notes, and snippets.

@leostera
Last active February 21, 2022 09:56
Show Gist options
  • Save leostera/affbf56e5cb1ea52c4035ec2dfdc3dea to your computer and use it in GitHub Desktop.
Save leostera/affbf56e5cb1ea52c4035ec2dfdc3dea to your computer and use it in GitHub Desktop.
type QueueOpts = {
maxConcurrency: Number;
};
type Task<R> = () => Promise<R>;
class ConcurrentQueue<R> {
opts: QueueOpts = {
maxConcurrency: 1
};
tasks: Task<R>[] = [];
results: R[] = [];
constructor(opts: QueueOpts) {
this.opts = opts;
}
public async run(tasks: Task<R>[]): Promise<R[]> {
this.tasks = tasks;
const workers: Promise<R | "done">[] = new Array(this.opts.maxConcurrency)
.fill(0)
.map((_) => this.doWork());
await Promise.all(workers);
return this.results;
}
async doWork(): Promise<R | "done"> {
let nextTask = this.tasks.shift();
if (nextTask === undefined) return "done";
let result = await nextTask();
this.results.push(result);
return this.doWork();
}
}
const queue = new ConcurrentQueue({
maxConcurrency: 2
});
let delay = (ms: number) =>
new Promise((resolve) => setTimeout(() => resolve(true), ms));
let log = async (ms: number, msg: string) => {
await delay(ms);
console.log(msg);
return msg;
};
let tasks: Task<String>[] = [
async () => log(2000, "I'm (even later) task #1!"),
async () => log(1000, "I'm (late) task #2!"),
async () => log(300, "I'm task #3!"),
async () => log(400, "I'm task #4!"),
async () => log(200, "I'm task #5!"),
async () => log(500, "I'm task #6!"),
async () => log(50, "I'm task #7!"),
async () => log(1, "I'm task #8!")
];
let results = await queue.run(tasks);
console.log("Results: ", results);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment