Promises in JavaScript provide a powerful way to handle asynchronous operations. One commonly used utility function is Promise.all()
, which allows you to execute multiple promises concurrently and wait for all of them to complete. In this blog post, we'll dive into creating our own Promise.all()
.
Understanding Promise.all()
The native Promise.all()
method takes an array of promises and returns a new promise. This new promise fulfills with an array of resolved values when all the input promises have been fulfilled, or rejected with the reason for the first promise that was rejected. It's a convenient way to handle multiple asynchronous tasks simultaneously.
Building Our Own promiseAll()
Let's start by creating a custom promiseAll()
function. Here's a simple implementation:
function promiseAll(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
reject(new TypeError('Promises must be an array'));
return;
}
const results = [];
let completedCount = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then((result) => {
results[index] = result;
completedCount++;
if (completedCount === promises.length) {
resolve(results);
}
})
.catch((error) => {
reject(error);
});
});
if (promises.length === 0) {
resolve(results);
}
});
}
Breaking Down the Code
Type Check:
- Ensure that the input is an array of promises. If not, reject with a
TypeError
.
- Ensure that the input is an array of promises. If not, reject with a
Initialization:
Initialize an array to store the results.
Keep track of the number of promises that have completed.
Iterating Over Promises:
Use
forEach
to iterate over each promise.Convert each promise to a resolved promise using
Promise.resolve()
.
Handling Resolved Promises:
When a promise resolves, store its result in the corresponding index of the results array.
Increment the completed count.
Checking Completion:
- Check if all promises have completed. If so, resolve the main promise with the array of results.
Handling Empty Array:
- If the input array is empty, resolve the main promise immediately
Example Usage:
Now, let's demonstrate the usage of our custom promiseAll()
:
const promise1 = Promise.resolve(1);
const promise2 = new Promise((resolve) => {
setTimeout(() => resolve(2), 1000))
};
const promise3 = Promise.reject('Error in promise 3');
promiseAll([promise1, promise2, promise3])
.then((results) => {
console.log('All promises fulfilled:', results);
})
.catch((error) => {
console.error('One of the promises rejected:', error);
});
In this example, we have three promises, one resolving immediately, one resolving after a timeout, and one rejecting. The promiseAll()
function will handle these promises concurrently and provide the results or the reason for rejection.
By implementing our own promiseAll()
, we gain a deeper understanding of how promise concurrency works and the underlying mechanics of the native Promise.all()
.