← Questions

Run promise tasks with bounded concurrency

0
WaymoCodingLast asked May 2026

In TypeScript, write a scheduler that runs a list of async tasks with at most limit running at once. Each task is a function that returns a promise. Start the next task as soon as one finishes, never fail fast, and resolve with every task's outcome in the original order.

Interface

Unless you agree on a different interface with the interviewer, assume:

type Settled<T> = { status: "fulfilled"; value: T } | { status: "rejected"; reason: unknown };

function runWithLimit<T>(tasks: Array<() => Promise<T>>, limit: number): Promise<Settled<T>[]>;
  • Each task factory is called exactly once. A task that throws synchronously counts as rejected, like one whose promise rejects.
  • The result array is in input order, whatever order tasks finish in.
  • A limit that is not a positive integer rejects immediately, before any task starts. An empty task list resolves to [].

Example

tasks: A (300 ms, resolves "a"), B (100 ms, rejects "boom"), C (100 ms, resolves "c")
runWithLimit(tasks, 2)

t=0    start A, B
t=100  B rejects -> start C
t=200  C resolves
t=300  A resolves
result: [{fulfilled, "a"}, {rejected, "boom"}, {fulfilled, "c"}]

Constraints

  • At no moment are more than limit tasks in flight.
  • Works for limit greater than the number of tasks.

Clarifying questions

  • On a rejection, keep going or stop everything?
  • Results in input order or completion order?
  • What should happen with limit 0, negative or fractional?
  • Is cancellation needed?

What a strong answer covers

  • A pool of limit workers that each pull the next index from a shared counter, or a launchNext called from each task's finally.
  • Wrapping each call in Promise.resolve().then(task) or try/catch so synchronous throws become rejections.
  • Writing results by index so order is preserved; resolving only after every task settles.
  • Validating limit up front, and the empty-list case.
  • Deterministic tests of the cap with controllable fake promises (count in-flight tasks and assert the maximum).

Follow-ups

  • Add cancellation with an AbortSignal.
  • Add a per-task timeout.
  • Tasks have priorities, and new tasks can be added while running.
Write and test your solution herePython in your browser, the question's tests level by level, every submission kept for you.Sign in to start coding