Concurrency Patterns
waiting for multiple Promises to settle
all settled:
await Promise.allSettled([p1, p2, p3])
console.log(await Promise.allSettled([
new Promise(resolve => setTimeout(resolve)),
"value",
Promise.reject(new Error("error")),
]))
Expected output:
[
{ status: "fulfilled", value: undefined },
{ status: "fulfilled", value: "value" },
{
status: "rejected",
reason: Error: error
}
]
all fulfilled or first rejected:
await Promise.all([p1, p2, p3])
first fulfilled, reject only when all rejected:
await Promise.any([p1, p2, p3])
first settled:
await Promise.race([p1, p2, p3])
limiting concurrency
runWithConcurrencyLimit executes an array of asynchronous tasks with
a specified concurrency limit, ensuring that no more than the given
number of tasks run concurrently and returning the results once all
tasks are completed.
function runWithConcurrencyLimit<T>(
tasks: Array<() => Promise<T>>,
concurrency: number
): Promise<Array<T>> {
return new Promise((resolve, reject) => {
if (tasks.length === 0) {
resolve([])
}
const results: Array<T> = []
let currentIndex = 0
let completed = 0
const next = () => {
const index = currentIndex++
tasks[index]().then(result => {
results[index] = result
if (++completed >= tasks.length) {
resolve(results)
return
}
if (currentIndex < tasks.length) {
next()
}
}, reject)
}
for (let i = 0; i < Math.min(concurrency, tasks.length); i++) {
next()
}
})
}