Skip to content

Instantly share code, notes, and snippets.

@toptensoftware
Created November 15, 2022 06:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toptensoftware/b9165470589b05ad15451d90db65d814 to your computer and use it in GitHub Desktop.
Save toptensoftware/b9165470589b05ad15451d90db65d814 to your computer and use it in GitHub Desktop.
// Runs tasks in parallel with a max concurrency.
// - `tasks` param should be an iterable collection of promises
// - `concurrency` is the maximum number of tasks to run at once
// - returns an array of results in same order as returned from
// the tasks. Each result is an object with either `value` key
// if the promise returned a value, or `error` if the task threw
// an error.
async function runParallel(tasks, concurrency)
{
return new Promise((resolve) => {
let inFlight = 0;
let results = [];
// Queue the first N tasks
for (let i=0; i<concurrency; i++)
{
queueNext();
}
function queueNext()
{
// Get the next task
let task = tasks.next();
if (task.done)
{
// No more tasks, when none in flight resolve the promise
if (inFlight == 0)
resolve(results);
return;
}
// Remember we have an in-flight promise running
inFlight++;
// Create result entry for this task
let result = {};
results.push(result);
// Wait for it to finish
task.value
.then(function(value) {
if (value !== undefined)
result.value = value;
})
.catch(function(error) {
result.error = error;
})
.finally(function() {
inFlight--;
queueNext();
});
}
});
}
// Async sleep function that logs entry/exit
async function sleep(name, milliseconds)
{
return new Promise(function (resolve, reject) {
console.log(`starting ${name}`);
setTimeout(function() {
console.log(`finished ${name}`);
if (name.startsWith('#'))
reject("Naughty");
resolve();
}, milliseconds);
});
}
(async function() {
let results = await runParallel(function*(){
yield sleep("A", 2000);
yield sleep("#B", 2000);
yield sleep("C", 750);
yield sleep("D", 2000);
}(), 2);
console.log(results);
console.log("Finished");
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment