Facebook Pixel

Concurrency Limited Task Scheduler

JavaScript
medium
30 mins

You are given an array of asynchronous functions called tasks, where each function returns a Promise resolving to a value. Your goal is to implement a function that executes these tasks with a concurrency limit that is, no more than maxConcurrent tasks can be running at the same time.

Once a task finishes, the scheduler should immediately start the next task (if any remain). The order of returned results should match the order of the input tasks, regardless of the order in which they resolve.

This is a classic problem often seen in API batching, file uploads, and load-balanced parallel computing.

Input:

  • tasks: An array of functions () => Promise<T> — each function returns a promise that resolves to any primitive value (e.g., number, string).
  • maxConcurrent: A positive integer indicating the maximum number of tasks that can run in parallel at any given time.

Output:

  • A Promise that resolves to an array of values, in the same order as the input tasks array.
  • Each element in the result corresponds to the resolved value of its respective task.

Constraints & Edge Cases:

  • 1 <= tasks.length <= 1000
  • 1 <= maxConcurrent <= tasks.length
  • Each task function:
  • Returns a promise that resolves successfully (you may optionally handle errors, but it's not required unless specified).
  • May resolve at different speeds (simulate delay with setTimeout).
  • Tasks should start execution as soon as a slot is available (i.e., don’t batch unnecessarily).
  • The resolved result must maintain the input order regardless of the order in which tasks complete.
  • Ensure no more than maxConcurrent tasks are actively running at any time.
  • Support cases where maxConcurrent === 1 (fully sequential).
  • Should work correctly even if all promises resolve immediately or have 0ms delay.
  • Bonus: Prevent stack overflow or performance issues when tasks.length is large (optional for extra credit).

Example Inputs & Outputs

// Example 1: maxConcurrent = 2, each task resolves after a delay const tasks = [ () => delayTask(100, "A"), () => delayTask(50, "B"), () => delayTask(10, "C"), ]; const maxConcurrent = 2; Output: ["A", "B", "C"] // Explanation: Two tasks can run at once. "B" and "C" may finish before "A", // but results are returned in the same order as the task list. // Example 2: maxConcurrent = 1 (sequential execution) const tasks = [ () => delayTask(10, 1), () => delayTask(20, 2), () => delayTask(30, 3), ]; const maxConcurrent = 1; Output: [1, 2, 3] // Explanation: Only one task runs at a time, so tasks run in order and complete sequentially. // Example 3: All tasks resolve immediately const tasks = [ () => Promise.resolve("X"), () => Promise.resolve("Y"), () => Promise.resolve("Z"), ]; const maxConcurrent = 3; Output: ["X", "Y", "Z"] // Explanation: All tasks complete instantly. No concurrency constraints are hit. // Example 4: maxConcurrent > tasks.length const tasks = [ () => delayTask(5, "first"), () => delayTask(5, "second"), ]; const maxConcurrent = 5; Output: ["first", "second"] // Explanation: All tasks can run at the same time since concurrency limit is higher than task count. // Helper used in test examples function delayTask(ms, result) { return () => new Promise(resolve => setTimeout(() => resolve(result), ms)); }

Companies:

swiggy
adobe

Solve Similar questions 🔥

Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.