Implementing Promise.all()
May 25, 2023 • 3 min read
In the vast trivia-like world of front-end interviewing, one of the questions I like to ask or be asked involves implementing Promise methods. These questions require a person to actual show if they understand how JavaScript handles asynchronous tasks with Promises which I do think is a fundamental skill when working with JavaScript.
One of the Promise methods that I want to go through today is Promise.all()
.
Promise.all()
takes an iterable of promises as input and returns a single Promise
as a result that resolves to be an array of fulfillment values if we successfully fulfilled all the promises.
Otherwise, we reject if any of the promises are rejected.
Let’s create a function stub to start.
/**
* @param {Promise[]} promises
* @returns {Promise}
*/
Promise.prototype.all = function (promises) {};
The first thing I would think to do is create a result array that we can use to store the results of our fulfilled promises.
/**
* @param {Promise[]} promises
* @returns {Promise}
*/
Promise.prototype.all = function (promises) {
const result = new Array(promises.length);
};
Next, we also know that we want to make sure that we keep track of how many promises are left to be fulfilled. We can create a variable
called unresolved
and set this variable to be the length of our promises iterable.
/**
* @param {Promise[]} promises
* @returns {Promise}
*/
Promise.prototype.all = function (promises) {
const numPromises = promises.length;
const result = new Array(numPromises);
let unresolved = numPromises;
};
Since we’re returning a Promise, we want to make sure our return value is a Promise. We should also move all the variables we created previously into the Promise callback.
/**
* @param {Promise[]} promises
* @returns {Promise}
*/
Promise.prototype.all = function (promises) {
return new Promise((resolve, reject) => {
const numPromises = promises.length;
const result = new Array(numPromises);
let unresolved = numPromises;
});
};
In the Promise callback, we’re going to iterate over the promises.
For each Promise, we’re going to try and await
to resolve or reject the values.
If we resolve a value successfully, we’re going to want to update our unresolved
variable by decrementing it.
If unresolved
is 0, then this means that we can call resolve
with our result
array.
If any of our promises are rejected, then we should call reject
with some error message.
/**
* @param {Promise[]} promises
* @returns {Promise}
*/
Promise.prototype.all = function (promises) {
return new Promise((resolve, reject) => {
const numPromises = promises.length;
const result = new Array(numPromises);
let unresolved = numPromises;
if (unresolved === 0) {
resolve(result);
return;
}
promises.forEach(async (promise, index) => {
try {
const value = await promise;
result[index] = value;
unresolved--;
if (unresolved === 0) {
resolve(result);
}
} catch (err) {
reject(err);
}
});
});
};
Hope you learned something about how Promise methods can be implemented.