Similar Problems

Similar Problems not available

Promise Pool - Leetcode Solution

Companies:

LeetCode:  Promise Pool Leetcode Solution

Difficulty: Unknown

Topics: unknown  

Problem Statement:

The problem is to write a function that takes an array of functions and returns a new function that executes the functions in parallel, with a configurable concurrency limit.

Function Signature:

The function signature is:

function promisePool(functions, limit) : Promise<void>

where:

  • functions is an array of functions that can return a Promise.
  • limit is a number that indicates the maximum number of functions that can be executed in parallel.

The returned Promise resolves when all the functions have completed.

Example:

const fn = (time) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(time);
    }, time);
  });
};

const arr = [() => fn(200), () => fn(100), () => fn(300), () => fn(400), () => fn(500)];

promisePool(arr, 2).then(() => {
  console.log("All the functions have completed");
});

The output of the above code will be:

All the functions have completed

The functions in the arr array will be executed in parallel, with a concurrency limit of 2.

Detailed Solution:

To solve this problem, we will use the Promise and async/await features of JavaScript.

  1. First, we create a function promisePool that takes two arguments - an array of functions functions and a number limit:
function promisePool(functions, limit) : Promise<void>  {
    // todo
}
  1. In the promisePool function, we create an array running that will keep track of the functions that are currently running:
let running = [];
  1. We create a function execute that will be called for each function in the functions array. The execute function takes a function func and returns a Promise. Inside the execute function, we first push the func to the running array and then execute the func.
function execute(func) {
    running.push(func);
    return func().finally(() => {
        running.splice(running.indexOf(func), 1);
    });
}

Note that we use the finally method of the Promise to remove the func from the running array after it is completed.

  1. We create a function limitFn that will be called for each function in the functions array. The limitFn function takes a function func and returns a Promise. Inside the limitFn function, we check if the running array has fewer than limit elements. If there are fewer than limit elements, we execute the func immediately using the execute function. Otherwise, we wait for the Promise of the first element in the running array to resolve and then execute the func.
async function limitFn(func) {
    while (running.length >= limit) {
        await Promise.race(running);
    }
    return execute(func);
}
  1. Finally, we call the limitFn function for each function in the functions array using the map method of the array. Then, we wait for all the returned Promises to resolve using the Promise.all function.
Promise.all(functions.map(limitFn));
  1. The complete implementation of the promisePool function is given below:
function promisePool(functions, limit) {
    let running = [];

    function execute(func) {
        running.push(func);
        return func().finally(() => {
            running.splice(running.indexOf(func), 1);
        });
    }

    async function limitFn(func) {
        while (running.length >= limit) {
            await Promise.race(running);
        }
        return execute(func);
    }

    return Promise.all(functions.map(limitFn));
}

Note:

  • In the execute function, we use finally instead of then to remove the func from the running array because we want to remove the func regardless of whether it is successful or not.
  • In the limitFn function, we use while (running.length >= limit) instead of if (running.length >= limit) to ensure that we do not exceed the concurrency limit even if multiple Promises are resolved at the same time.
  • We can handle errors in the functions by adding a catch block inside the execute function.

Promise Pool Solution Code

1