Lets create our very own Promise.all!

Gunjan Kalita
3 min readFeb 24, 2023

Let me start with this,

Creating your own Promise.all is what some smart JavaScript minds might ask you during an interview. Lets attempt to be ready for it with this blog.

Understanding the question:

Create your own Promise.all polyfill. In other words, please create your own Promise.all implementation.

Let’s first understand what Promise.All does. This is a function that takes an array of promises and returns a new promise that resolves with an array of all the results from the individual promises. Lets see an example.

// 3 promises 
const p1 = new Promise((resolve, reject) => {
resolve('P1')
})

const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('P2')
}, 1000);
})

const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('P3')
}, 0);
})

const p4 = 'some rendom string'

Promise.all([p1, p2, p3, p4]).then(data => {
// TODO: data
console.log(data)
}).catch(e => {
// Error triggered if any of these promises fails.
})

// Output: [ 'P1', 'P2', 'P3' ] <= returned from then block

We will go step by step.

Step 1: Create a function that takes an array of promises and returns a promise.

This is very simple.

// Custom Promise.All 

const allX = (promiseArr) => {
return new Promise((resolve, reject) => {
// TODO: core implementation.
});
}

Step 2: Run All the promises in the array. Reject the promise if any one fails.

// Custom Promise.All 

const allX = (promiseArr) => {
return new Promise((resolve, reject) => {
promiseArr.forEach((promise, index) => {
promise.then((data) => {

}).catch(e => {
// reject when any of the promises fails.
reject(e)
})
})
});
}

Step 3: Resolve with an array of responses after all promises are resolved.

This involves two steps.
- create an array and store the responses coming from the promises.
- Call resolve after all promises are done. For that we will keep a count.

// Custom Promise.All 

const allX = (promiseArr) => {
const responses = []
let count = 0;
return new Promise((resolve, reject) => {
promiseArr.forEach((promise, index) => {
promise.then((data) => {
responses[index] = data;
count ++

// check to resolve.
if (promiseArr.length === count) {
resolve(responses)
}
}).catch(e => {
// reject when any of the promises fails.
reject(e)
})
})
});
}

Step 4: Make it available at Promise object

Finally, make it available at the promise object itself.

Promise.allX = allX

Step 5: Handle edge case

Till now we are in great shape with our own Promise.all. But, we need to handle some edge cases here. Promise.all works very well even with items being not a promise (like p4 ). We need to handle the scenario in our code so that non promise expressions in the array are also handled nicely. For that we will use the Promise.resolve function to convert these values to a always resolving promise..

const allX = (promiseArr) => {
const responses = []
letcount = 0;
return new Promise((resolve, reject) => {
promiseArr.forEach((value, index) => {
let promise = value;
// check if valid promise
if(!(value instanceof Promise)) {
promise = Promise.resolve(value)
}
promise.then((data) => {
responses[index] = data;
count ++

// check to resolve.
if (promiseArr.length === count) {
resolve(responses)
}
}).catch(e => {
// reject when any of the promises fails.
reject(e)
})
})
});
}

This will be enough for keep things going. Questions ?? Feel free to ask.

--

--

Gunjan Kalita

Javascript | React | Node | MongoDB | MySQL. SDE 2 at Swiggy | DM for a free CV review