Creating a Promise.any() polyfill
A comprehensive explanation to the BigFrontEnd - 34. Implement Promise.any()
Photo by Rahul Mishra on Unsplash
Problem Link: https://bigfrontend.dev/problem/implement-Promise-any
First things first, as usual :)
What is a Promise?
An object that represents an eventual completion of failure of an asynchronous operation
What is a polyfill?
A function or a snippet of code that mimics a particular functionality. Created majorly to provide desired functionality in older browsers which don’t support latest, usually higher order operations
What is Promise.any() ?
A static method that takes an iterable of promises and resolves to the value of the first resolved promise, if not , it rejects when all the promises reject, by combining all the error reasoning using the AggregateError
constructor
Approach
Return a promise
Have a counter variable to keep track of rejected promises and an array to store the error’s for the corresponding promises
Loop over the given promises array:
For each promise, if it resolves, directly resolve the main promise
Else, when it fails, store the error at the appropriate index and increment the error counter
If the error counter equals the length of given promises array, it means none of the promises were resolved and all of them were rejected.
Hence, combine all the errors by passing the error array to the
AggregateError
constructor to the reject function of the main promise function.
Code Breakdown and explanation
function any(promises) {
// Edge Case: Empty array
if (promises.length === 0) {
return Promise.reject(new AggregateError('No promises were passed', []));
}
// rejectCount keeps track of the number of promises reject,
// which will help us to identify if all the promises are rejected
let rejectCount=0, rejectedPromisesArr = [];
// return a Promise
return new Promise((resolve,reject) => {
promises.forEach((promise,i) => {
Promise.resolve(promise)
// If a Promise is resolved ,directly resolve it
.then(resolve)
.catch(err => {
// If it fails, store the error at corresponding index of the rejected Promise
rejectedPromisesArr[i] = err
// Increment the rejected count
rejectCount++;
// Once the rejection count matches the length of the given promises array
// i.e all the Promises are rejected,
// it's time we reject the main promise function by
// passing rejectPromisesArr to the AggregateError constructor
if(rejectCount === promises.length) reject(new AggregateError("No promises resolved",rejectedPromisesArr))
})
})
})
}
And that’s it, we have successfully implemented the Promise.any() polyfill.
It’s a bit tricky question, so are most of the Promises polyfills. But functionally it’s the opposite of Promise.all(), you can find it’s blog here
A positive thought for you incase you made it till here!