promise.all()

Hard ImportantFlipkartBirdeyeTiktokByteDance

Prompt

Implement a function called customPromiseAll that takes an array of promises as input and returns a new promise that resolves with an array of resolved values from the input promises, or rejects with the reason of the first promise that was rejected.

The function should have the following signature:

/**
* Implement the `customPromiseAll` function
* @param {Array<Promise>} promises - An array of Promises
* @returns {Promise<Array>} - A new Promise that resolves with an array of resolved
* values from the input promises, or rejects with the
* reason of the first promise that was rejected.
*/
function customPromiseAll(promises) {
// Your implementation here
}

The customPromiseAll function should behave similar to the native Promise.all method in JavaScript, but you cannot use Promise.all in your implementation.

Here are some examples to test your solution:

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});

customPromiseAll([promise1, promise2, promise3]).then(
(values) => {
console.log(values); // Expected output: [3, 42, "foo"]
}
);
const promise1 = Promise.reject('Error 1');
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

customPromiseAll([promise1, promise2, promise3])
.then((values) => {
console.log(values); // This line should not be reached
})
.catch((error) => {
console.log(error); // Expected output: "Error 1"
});
customPromiseAll([]).then((values) => {
console.log(values); // Expected output: []
});

Your implementation should handle various cases, including an empty input array, a mix of resolved and rejected promises, and promises that resolve with non-Promise values.

Hint 1

Start by creating a new Promise that will be returned by the customPromiseAll function. This Promise will be resolved or rejected based on the outcome of the input promises. You'll need to create a Promise executor function that handles the resolution or rejection of the outer Promise.

Hint 2

Inside the Promise executor function, you need to iterate over the input array of promises. You can use a for loop or the forEach method to iterate over the array. For each promise in the array, ensure that it is a Promise object by calling Promise.resolve(promise). This will handle both Promise and non-Promise values.

Hint 3

After ensuring that each value is a Promise object, you need to handle its resolution or rejection. Chain a then handler to handle the resolved value and a catch handler to handle the rejected promise. In the then handler, you'll need to store the resolved values in an array. In the catch handler, you'll need to reject the outer Promise with the reason for rejection.

Hint 4

As you're handling each promise, keep track of the number of resolved promises. When the number of resolved promises is equal to the length of the input array, it means that all promises have been resolved. At this point, you can resolve the outer Promise with the array of resolved values. If any promise is rejected before all promises are resolved, the outer Promise should be rejected with the reason for rejection.

Solution

Explanation

  • The function takes an array of promises as input.
  • It initializes an empty array results to store the resolved values from the input promises.
  • It initializes a variable completedPromisesCount to keep track of the number of promises that have been resolved.
  • The function creates and returns a new Promise.
  • Inside the Promise executor function, it iterates over the input promises array using the forEach method.
  • For each promise in the array:
    • It calls Promise.resolve(promise) to ensure that the value is a Promise object, even if it's a non-Promise value like a number or a string.
    • It chains a then handler to the resolved Promise, which:
      • Increments the completedPromisesCount counter.
      • Stores the resolved value in the results array at the corresponding index (results[index] = value).
      • If all promises have been resolved (completedPromisesCount === promises.length), it resolves the outer Promise with the results array.
    • It also chains a catch handler to handle any rejected promises, which rejects the outer Promise with the reason for rejection.
  • If the input promises array is empty, the outer Promise is immediately resolved with an empty array.

Key Aspects

  • Handling non-Promise values: By calling Promise.resolve(promise), the solution ensures that even non-Promise values are wrapped in a Promise object before being handled.
  • Collecting resolved values: The resolved values from each Promise are stored in the results array at the corresponding index (results[index] = value).
  • Tracking completed promises: The completedPromisesCount counter is used to keep track of how many promises have been resolved. When all promises have been resolved (completedPromisesCount === promises.length), the outer Promise is resolved with the results array.
  • Handling rejected promises: If any Promise is rejected, the catch handler rejects the outer Promise with the reason for rejection. This ensures that the first rejected promise causes the entire customPromiseAll Promise to reject, following the behavior of the native Promise.all method.
  • Handling empty input array: If the input promises array is empty, the outer Promise is immediately resolved with an empty array, as per the expected behavior of Promise.all.
00:00

Table of Contents