This is the senior async question. It separates people who know Promise.all from people who understand concurrency control — and it shows up whenever you must avoid hammering an API or the file system.
Promise.all starts everything at once. Here you only want limit tasks running concurrently:
Set and let each one remove itself on settle.await Promise.race(inFlight) — that resolves as soon as one finishes, freeing a slot.Promise.all(results) returns them in input order regardless of finish time..then(remove, remove) so both success and failure free the slot.Promise.all rejects on the first failure; mention allSettled if the task should be resilient.AbortSignal?" → check signal.aborted before launching each task.Build the pool, then verify with the second test case that the in-flight count never exceeds the limit.
async function asyncPool(limit, items, iteratorFn) { // run iteratorFn(item) over all items, at most `limit` at a time, // resolving to results in input order } const sleep = (ms, v) => new Promise((r) => setTimeout(() => r(v), ms)); asyncPool(2, [100, 50, 30], (ms) => sleep(ms, ms)).then(console.log); // [100, 50, 30]
Test Code
Enter JavaScript that runs after your solution. It should return a value or a Promise.