In the previous posts of this series, I've shown the resolve
and reject
methods of a Promise and also how to retrieve data from a Promise using Promise.then()
and Promise.catch()
methods.
[ https://dev.to/swarnaliroy94/retrieving-data-from-promise-then-catch-3onk ]
We can make this process more compact using Async/Await
, which is most popularly used in projects. But, before writing about Async/Await, I want to make the readers familiar with some other methods of Promise.
The methods that I'm going to show in this post are Promise.all()
, Promise.race()
, Promise.any()
& Promise.finally()
.
Let's get started then!!
◼️ Promise.all() Method
👉 The Promise.all()
method accepts an iterable Object, such as an Array of promises as an input and returns a single promise that resolves to a result array of the input promises.
👉 When all input promises have been resolved or the iterable input does not contain a promise, the returned promise will be resolved.
👉 It rejects immediately when an input promise rejects or non-promise throws an error and will reject with that first rejection message / error message.
👉 It is often used when there are many asynchronous tasks involved that the overall code relies on to work successfully - all of the ones we want to do before we continue to execute the code.
👉 This method aggregates the results of multiple promises.
Fulfillment of Promise.all()
🔹 When an empty iterable is passed, the promise returned by this method is executed synchronously. The resolved value will be an empty array.
🔹 When a non-empty iterable is passed, and all of the promises fulfill or are not promises,the promise returned by this method will be executed asynchronously.
Following is an example of Promise.all()
Method 👇
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 300, "resolved");
}); //will be resolved after 300ms
const promise2 = 93; //non-promise
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "resolved2");
}); // will be resolved after 100ms
Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log(values);
})
.catch((err) => {
console.log(err);
});
//expected output: [ 'resolved', 93, 'resolved2' ]
Rejection of Promise.all() : Fail-Fast Behavior
Promise.all()
shows fail-fast behavior, that is, Promise.all() asynchronously rejects with the value of the promise that rejected, if any of the passed-in elements are rejected.
For example, if we pass in two promises that resolve after a timeout and one promise that rejects immediately, then Promise.all() will reject immediately. It does not depend on if the other promises have resolved. The following example just does the same!
const pro1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("one"), 1000);
});
const pro2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("two"), 2000);
});
const pro3 = new Promise((resolve, reject) => {
setTimeout(() => reject("rejected"), 3000);
});
Promise.all([pro1, pro2, pro3])
.then((values) => {
console.log(values);
})
.catch((error) => {
console.log(error);
});
//expected output: rejected
Let's move to another method which is Promise.any()
.
◼️ Promise.any() Method
👉 The Promise.any()
takes an iterable Object, such as an Array of promises as an input. Once a promise is fulfilled, a single promise is returned and the promise is resolved using the value of the promise.
👉 If no promises in the iterable fulfill (if all of the given promises are rejected), then the returned promise is rejected with an AggregateError (that groups together individual errors).
Fulfillment of Promise.any()
🔹 Unlike Promise.all()
, this method is used to return the first promise that fulfills.
🔹 It is short-circuited right after a promise is completed, so as soon as a promise is fulfilled, it will not wait for other promises to complete.
🔹 When a non-empty iterable is passed, and any of the promises fulfill, or are non-promises, then the promise returned by this method is fulfilled asynchronously.
For Example, the following code snippet will resolve the QuickyDone promise first as it is resolved after 100ms and the other one resolves after 500ms. It will not wait for any other promise to be fulfilled but immediately return the first promise that resolves.
const SlowlyDone = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "Done slowly");
}); //resolves after 500ms
const QuicklyDone = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "Done quickly");
}); //resolves after 100ms
const Rejection = new Promise((resolve, reject) => {
setTimeout(reject, 100, "Rejected"); //always rejected
});
Promise.any([SlowlyDone, QuicklyDone, Rejection])
.then((value) => {
console.log(value);
// QuicklyDone fulfils first
})
.catch((err) => {
console.log(err);
});
//expected output: Done quickly
Rejection of Promise.any()
🔹 Promise.any() rejects with an AggregateError if no promise fulfils.
🔹 The AggregateError object represents an error when several errors need to be wrapped in a single error. It is thrown when multiple errors need to be reported by an operation.
An example is shown below 👇
const Rejection = new Promise((resolve, reject) => {
setTimeout(reject, 100, "Rejected"); //always rejected
});
Promise.any([Rejection])
.catch((err) => {
console.log(err);
});
// expected output: "AggregateError: No Promise in Promise.any was resolved"
⭐ Note that, Promise.any() was supported in node.js 15.0.0. If your node.js version is older than that, the console might show a TypeError: Promise.any is not a function message, so you need to update it and try again.
◼️ Promise.prototype.finally()
👉 The finally()
method returns a Promise.
👉 When a Promise is completed, either resolved or rejected,this specified callback function is executed.
👉 This helps to avoid duplicating code in both the promise's then() and catch() handlers.
👉 The finally() method will help if you're going to do any processing or cleanup work once a promise is made, regardless of the outcome.
The following is a simple example of this method.👇
const addition = (a, b) =>
new Promise((resolve, reject) => {
if (typeof a == "number" && typeof b == "number") {
resolve(a + b);
} else {
reject("Not a Number");
}
});
addition(10, 5)
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
})
.finally(() => {
console.log("Numbers are added");
});
/* expected output: 15
Numbers are added */
◼️ Promise.race() Method
👉 The Promise.race()
method returns a Promise that is resolved or rejected, as soon as one of the promises in an iterable, such as an array, fulfills or rejects, with the value or reason from that Promise.
👉 The promise returned will be forever pending, if the iterable passed is empty.
👉 Promise.race()
will resolve to the first value found in the iterable, if the iterable contains one or more non-promise value or an already settled promise.
Let's see an example of Promise.race() with setTimeout 👇
const pro1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("one"), 200);
});
const pro2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("two"), 100);
});
Promise.race([pro1, pro2])
.then((response) => {
console.log(response); //output: two
})
.catch((err) => {
console.log(err);
});
const pro3 = new Promise((resolve, reject) => {
setTimeout(() => reject("rejected"), 300);
});
const pro4 = new Promise((resolve, reject) => {
setTimeout(() => resolve("four"), 400);
});
Promise.race([pro3, pro4])
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
}); //output: rejected
In the first case, pro2(100ms) is faster than pro1(200ms), so the output shows two. In the second case, pro3(300ms) is faster than pro4(400ms), so the promise rejects. So basically, Promise.race() takes the first settled Promise
If we take this same example and pass all the promises inside Promise.race()
, it will return two as output, as the pro2 is the fastest promise to be settled in this case.
const pro1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("one"), 200);
});
const pro2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("two"), 100);
});
const pro3 = new Promise((resolve, reject) => {
setTimeout(() => reject("rejected"), 300);
});
const pro4 = new Promise((resolve, reject) => {
setTimeout(() => resolve("four"), 400);
});
Promise.race([pro1, pro2, pro3, pro4])
.then((response) => {
console.log(response);
})
.catch((err) => {
console.log(err);
});
//output: two
Top comments (13)
You not mentioned
Promise.race()
.Now it's added. :)
Yes, I didn't mention that, I've mentioned these three because these are used most commonly. There are other methods as well , will mention them later.
There's this one too:
developer.mozilla.org/en-US/docs/W...
Yeah.. thank you.. will include that also later
I'm use Promise.race to add timeouts to fetch calls, to make sure the calls don't remain hanged up connections open.
More
Nice explaination :) Thank you for putting the post
My pleasure.. Keep following for more posts..
Not mentioned
Promise.allSettled()
This is a good one. Thanks for sharing.
You're welcome. Keep following for more posts...
what happen with other promise in race condition ?