Created
November 15, 2022 06:52
-
-
Save toptensoftware/b9165470589b05ad15451d90db65d814 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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