Problem Statement

Implement an asynchronous function mapAsyncLimit that applies a callback function to each element of an iterable, limiting how many promises run concurrently.

Unlike batch-based processing, this version should start a new task as soon as one finishes, maintaining a constant concurrency level until all items are processed.

The function must:

  1. Support asynchronous callbacks.
  2. Limit the number of concurrent tasks to a specified size.
  3. Preserve the order of results.
  4. Reject immediately if any callback throws an error.
  5. Resolve to an empty array if the input iterable is empty.

Example

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const result = await mapAsyncLimit(
[1, 2, 3, 4, 5],
async (num) => {
await delay(100);
return num * 2;
},
2
);

console.log(result); // [2, 4, 6, 8, 10]

Constraints

  • iterable must be an array.
  • callbackFn must return a Promise.
  • size must be a positive integer (default: Infinity).