PracHub
QuestionsLearningGuidesInterview Prep
|Home/Software Engineering Fundamentals/Waymo

Run Promise Tasks with Bounded Concurrency

Last updated: Jul 14, 2026

Quick Overview

Implement a TypeScript promise scheduler with bounded concurrency and input-ordered settled results. Invoke each task factory exactly once, handle synchronous throws and asynchronous rejections without fail-fast behavior, reject invalid limits early, and test the concurrency cap deterministically.

  • medium
  • Waymo
  • Software Engineering Fundamentals
  • Frontend Engineer

Run Promise Tasks with Bounded Concurrency

Company: Waymo

Role: Frontend Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Onsite

# Run Promise Tasks with Bounded Concurrency The source reports a pure TypeScript or JavaScript coding round involving Promises, but it does not preserve the original problem statement. The following bounded-concurrency exercise is an explicit practice reconstruction, not a claim about the missing original prompt. Implement this TypeScript function: ```ts type Settled<T> = | { status: "fulfilled"; value: T } | { status: "rejected"; reason: unknown }; async function runWithLimit<T>( tasks: Array<() => Promise<T>>, limit: number, ): Promise<Array<Settled<T>>>; ``` Each task is a factory and must not be invoked before a worker slot is available. Invoke every task exactly once, run no more than `limit` task Promises at the same time, and return one settled result per input task in original input order. A task that throws synchronously is treated as rejected. One rejection does not prevent later tasks from starting. ### Constraints & Assumptions - `tasks` may be empty; return a Promise fulfilled with `[]`. - `limit` must be a positive integer. Otherwise, the returned Promise rejects with `RangeError` before any task is invoked. - A task is considered active from immediately before its factory is called until its returned Promise settles. - The function does not implement cancellation because the source gives no cancellation contract. - Do not use a library concurrency helper. ### Clarifying Questions to Ask - Should one rejection stop scheduling, or should all tasks settle? - Must results preserve input order or completion order? - Can task factories throw before returning a Promise? - How should invalid limits, cancellation, and timeouts behave? - Is fairness beyond input-order scheduling required? ### Hints - Keep the next unscheduled index separate from the result slot being written. - Several asynchronous workers can pull indices from one shared counter because JavaScript runs each synchronous counter update to completion. - Catch both synchronous factory throws and Promise rejections through one Promise chain. ### What a Strong Answer Covers - At most `limit` active tasks and exactly one invocation per task. - Input-order results despite out-of-order completion. - Correct handling of empty input, invalid limits, synchronous throws, and asynchronous rejection. - No unhandled rejection and no fail-fast behavior under the stated contract. - A concise explanation of the event loop, microtasks, shared counter safety, complexity, and tests with controllable Promises. ### Follow-up Questions 1. How would you add fail-fast behavior without allowing already-running tasks to produce unhandled rejections? 2. How would an `AbortSignal` change task and scheduler contracts? 3. What changes if tasks are supplied as already-started Promises instead of factories? 4. How would you test the concurrency bound deterministically?

Quick Answer: Implement a TypeScript promise scheduler with bounded concurrency and input-ordered settled results. Invoke each task factory exactly once, handle synchronous throws and asynchronous rejections without fail-fast behavior, reject invalid limits early, and test the concurrency cap deterministically.

Related Interview Questions

  • Design and Implement a Cross-System Object Tracker - Waymo (medium)
  • Build a Debounced Autocomplete Search Bar - Waymo (medium)
  • Build an Interactive Filtered Tree View - Waymo (medium)
  • Debug an Angular UI from User Reports - Waymo (medium)
|Home/Software Engineering Fundamentals/Waymo

Run Promise Tasks with Bounded Concurrency

Waymo logo
Waymo
May 11, 2026, 12:00 AM
mediumFrontend EngineerOnsiteSoftware Engineering Fundamentals
2
0

Run Promise Tasks with Bounded Concurrency

The source reports a pure TypeScript or JavaScript coding round involving Promises, but it does not preserve the original problem statement. The following bounded-concurrency exercise is an explicit practice reconstruction, not a claim about the missing original prompt.

Implement this TypeScript function:

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

async function runWithLimit<T>(
  tasks: Array<() => Promise<T>>,
  limit: number,
): Promise<Array<Settled<T>>>;

Each task is a factory and must not be invoked before a worker slot is available. Invoke every task exactly once, run no more than limit task Promises at the same time, and return one settled result per input task in original input order. A task that throws synchronously is treated as rejected. One rejection does not prevent later tasks from starting.

Constraints & Assumptions

  • tasks may be empty; return a Promise fulfilled with [] .
  • limit must be a positive integer. Otherwise, the returned Promise rejects with RangeError before any task is invoked.
  • A task is considered active from immediately before its factory is called until its returned Promise settles.
  • The function does not implement cancellation because the source gives no cancellation contract.
  • Do not use a library concurrency helper.

Clarifying Questions to Ask Guidance

  • Should one rejection stop scheduling, or should all tasks settle?
  • Must results preserve input order or completion order?
  • Can task factories throw before returning a Promise?
  • How should invalid limits, cancellation, and timeouts behave?
  • Is fairness beyond input-order scheduling required?

Hints

  • Keep the next unscheduled index separate from the result slot being written.
  • Several asynchronous workers can pull indices from one shared counter because JavaScript runs each synchronous counter update to completion.
  • Catch both synchronous factory throws and Promise rejections through one Promise chain.

What a Strong Answer Covers Guidance

  • At most limit active tasks and exactly one invocation per task.
  • Input-order results despite out-of-order completion.
  • Correct handling of empty input, invalid limits, synchronous throws, and asynchronous rejection.
  • No unhandled rejection and no fail-fast behavior under the stated contract.
  • A concise explanation of the event loop, microtasks, shared counter safety, complexity, and tests with controllable Promises.

Follow-up Questions Guidance

  1. How would you add fail-fast behavior without allowing already-running tasks to produce unhandled rejections?
  2. How would an AbortSignal change task and scheduler contracts?
  3. What changes if tasks are supplied as already-started Promises instead of factories?
  4. How would you test the concurrency bound deterministically?
Loading comments...

Browse More Questions

More Software Engineering Fundamentals•More Waymo•More Frontend Engineer•Waymo Frontend Engineer•Waymo Software Engineering Fundamentals•Frontend Engineer Software Engineering Fundamentals

Write your answer

Your first approved answer each day earns 20 XP.

Sign in to write your answer.
PracHub

Master your tech interviews with 8,500+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • AI Coding Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.