Run promises with a concurrency limit
Write runWithConcurrency(tasks, limit). tasks is an array of functions that each return a promise (calling a task starts its work), and limit is a positive integer. The function returns a promise that follows these rules:
- at most
limittasks run at the same time - the next task starts as soon as any running task finishes (not in fixed batches of
limit) - it resolves with the results in the same order as
tasks, not in completion order - if a task rejects, it rejects with that error right away and starts no more tasks
Examples:
- with
limit = 2and tasks taking 100ms, 20ms and 20ms, the first two start immediately, the third starts at about 20ms, and the result is[r1, r2, r3] runWithConcurrency([], 3)→ resolves to[]- with
limit = 1the tasks run one after another, in order
Define runWithConcurrency in the editor. 7 tests will call it.
Hint 1Keep a shared index pointing at the next task to start, and a results array you fill by index.
Hint 2Start limit 'workers'. Each worker loops: take the next index, await that task, store the result at that index, and repeat until no tasks are left.
Hint 3Wait for all workers with Promise.all. To stop after a failure, set a flag when a task throws, and have every worker check it before starting another task.
one clean solution
async function runWithConcurrency(tasks, limit) {
const results = new Array(tasks.length);
let nextIndex = 0;
let failed = false;
async function worker() {
while (!failed && nextIndex < tasks.length) {
const index = nextIndex++;
try {
results[index] = await tasks[index]();
} catch (error) {
failed = true; // stop the other workers from picking up new tasks
throw error;
}
}
}
const workerCount = Math.min(limit, tasks.length);
await Promise.all(Array.from({ length: workerCount }, () => worker()));
return results;
}