promise.all()
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.
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.
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.
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.
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
resultsto store the resolved values from the input promises. - It initializes a variable
completedPromisesCountto 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
promisesarray using theforEachmethod. - 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
thenhandler to the resolved Promise, which:- Increments the
completedPromisesCountcounter. - Stores the resolved value in the
resultsarray at the corresponding index (results[index] = value). - If all promises have been resolved (
completedPromisesCount === promises.length), it resolves the outer Promise with theresultsarray.
- Increments the
- It also chains a
catchhandler to handle any rejected promises, which rejects the outer Promise with the reason for rejection.
- It calls
- 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
resultsarray at the corresponding index (results[index] = value). - Tracking completed promises: The
completedPromisesCountcounter 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 theresultsarray. - Handling rejected promises: If any Promise is rejected, the
catchhandler rejects the outer Promise with the reason for rejection. This ensures that the first rejected promise causes the entirecustomPromiseAllPromise to reject, following the behavior of the nativePromise.allmethod. - Handling empty input array: If the input
promisesarray is empty, the outer Promise is immediately resolved with an empty array, as per the expected behavior ofPromise.all.