48Implement an asynchronous task runner with configurable concurrency
mediumAbout 35 minutesCodingpromisesconcurrencyqueuesclasses
Problem
Implement a TaskRunner class. Unlike a pool over a fixed list, tasks can be added at any time, and the concurrency can change while it runs.
new TaskRunner({ concurrency = 2 })add(task):taskis a function returning a promise (or a value). Returns a promise that settles with that task's result.setConcurrency(n): change the limit. Raising it starts waiting tasks immediately; lowering it lets running tasks finish but starts no more until there is room.onIdle(): a promise that resolves when nothing is running and nothing is waiting.runningandwaiting: the current counts.
const runner = new TaskRunner({ concurrency: 2 });
const thumbnail = runner.add(() => resize(image, 200));
const preview = runner.add(() => resize(image, 800));
runner.setConcurrency(navigator.hardwareConcurrency ?? 4);
await runner.onIdle();Requirements
- Tasks start in the order they were added.
- A failing task rejects only its own promise; the runner keeps going.
- A synchronous throw in a task counts as a failure of that task.
Try it yourself
Write your solution, run it, then submit to check it against the tests.
solution.jsJavaScript
Press Run or ⌘ Enter to execute your code.
Step-by-step
Each job stores the task plus the resolve and reject of the promise that add returned. add pushes a job and calls #pump().
Unlock the full solution
What's inside
- Step-by-step
- Approach
- Solution
- Complexity
- Edge cases
- Follow-up questions
- Tests
Includes 2 code listings, 4 edge cases, 4 follow-up questions.
One-time payment by UPI, card or net banking. Launch price.