Sent out once every month. No spam.
Promise.allSettled returns a promise when all inputs are settled that is either fulfilled or rejected.
Promise.all & Promise.allSettledPromise.all will reject as soon as one of the items in the input is rejected.Promise.allSettled will never reject and will wait until all inputs are settled.I am not so sure of many use-cases. But, we want to know how it works right?. In the below example, first, we will see how it works and then will implement it.
var APICall1 = fetch('https://reqres.in/api/users?page=1');
var APICall2 = fetch('https://reqres.in/api/users?page=2');
Promise.allSettled([APICall1, APICall2]).then((results) => {
results.forEach((result) => {
console.log(result); // Result is below
});
});
// Log:
// {status: "fulfilled", value: Response}
// {status: "fulfilled", value: Response}
Below is a simplified version of TC39 specs to understand its implementation details.
iterable object as an argument.not iterable, throw an exception with an error message.iterable.results in an array.resolved/rejected.results.First, we will write a function to find out if the passed value is iterable or not. We can use [Symbol.iterator] to find it out. Read more about the iterable here.
function isIterable(value) {
// If no argument is passed or === null
if (arguments.length === 0 || value === null) {
return false;
}
return typeof value[Symbol.iterator] === 'function';
}
isIterable({}); // false
isIterable(1); // false
isIterable(nul); // false
isIterable([]); // true
isIterable(''); // true
// String, Array, TypedArray, Map & Set are all built-in iterables
Next step is to wrap our iteration (forEach) with new Promise() object. So that when all our inputs are settled, we can return the results with status and value/reasons.
Implementation is quite similar to Promise.all() with a few changes.
// Our custom all settled function
function isAllPromiseSettled(promises) {
// To store our results
var results = Array(promises.length);
// To keep track of how many promises resolved
var counter = 0;
// If not iterable throw an error
if (!isIterable(promises)) {
throw new Error(`${typeof promises} is not iterable`);
}
// Wrapping our iteration with Promise object
// So that we can resolve and return the results on done.
return new Promise((resolve) => {
// Iterate the inputs
promises.forEach((promise, index) => {
// Wait for each promise to resolve
return Promise.resolve(promise)
.then((result) => {
counter++; // Increment counter
// Store status and result in same order
results[index] = { status: 'fulfilled', value: result };
// If all inputs are settled, return the results
if (counter === promises.length) {
resolve(results);
}
})
.catch((err) => {
counter++; // Increment counter
// Store status and reason for rejection in same order
results[index] = { status: 'rejected', reason: err };
// If all inputs are settled, return the results
if (counter === promises.length) {
resolve(results);
}
});
});
});
}
Yep, we did it. We learned what is Promise.allSettled() and implemented it. If you want to use it today, the browser support is pretty much available in all modern browsers.
The browser implementation might be different than ours. Nevertheless, you get the idea, right?
Thanks for reading till the end 😬. My next post is about Event Emitters (Pub/Sub). If you are not subscribed, subscribe below. See you next Tuesday ;)