You might or might not have worked with promises, but if you had a hard time understanding them or if you are looking for a concise explanation about promises, this article might help you. So without any delay, let's get started.
What is a Promise?
A promise is an object, which is a substitute value for some value that is not known at the time, it(Promise) is created. This 'some value', for example, could be the response, we get after making an API call. A promise allows us to attach the handlers for the asynchronous operations. As soon as these asynchronous operations are complete, instead of returning their actual value, a promise is returned, the value of which could be used in the future.
Remember that:
A promise is in one of the three states: Pending, Fulfilled or Rejected.
If a promise is fulfilled or rejected, it is said to be settled.
Once a promise is fulfilled or rejected, the respective handler (the success or the error handler callback function inside the
then
method) is called.
- Creating a JavaScript promise:
const promise = new Promise(); // error! this wouldn't create a promise.
As per the documentation, the promise constructor takes in a callback function called an executor function. This callback function needs to be passed to the promise constructor to initialize a promise. Yes, it's necessary!
Thus, a promise is initialized in the following manner:
const promise = new Promise(function(resolve, reject) {
});
- Now, remember that resolve and reject both are functions, don’t believe me? Just include this line of code in our previous code:
const promise = new Promise(function(resolve, reject) {
console.log(arguments);
});
Now open your chrome console, and you would be able to see a property called callee
what is it? A function!
You can pass anything to resolve, literally anything!
Passing a string to resolve:
const promise = new Promise(function(resolve, reject) { resolve("Hello world!"); }); promise.then(res => console.log(res));
Don't worry by looking at
then
, for now, just remember that by usingthen
we handle promises.Passing a variable to resolve:
const promise = new Promise(function(resolve, reject) { let message = "Hello world!" resolve(message); }); promise.then(res => console.log(res));
Passing a function to resolve:
const promise = new Promise(function(resolve, reject) { resolve(function() { console.log("Promise returned a function, when resolved!"); }); }); promise.then(res => res());
What is then and catch?
Whenever a promise is settled(i.e. either fulfilled or rejected), it needs to be handled. The then
is a method that helps us in handling the promise. This then
takes in two callback functions(if we pass both fulfill and error callbacks) or a single callback function(if we only pass a fulfill callback).
Similarly, catch
is also a handler, which gets executed whenever a promise is rejected.
If we pass only one callback function, we can use a separate catch()
for handling errors. For example,
Using
then
with a fulfill and error callback, run the following code and see the output:const promise = new Promise(function(resolve, reject) { // Rejecting a promise, to see if error callback get's executed or not. reject("Rejected"); }); promise.then(function() { console.log("Fulfilled"); }, function(err) { console.log(err); }); // Output: Rejected
Using
then
with only a fulfilled callback and a separatecatch
for handling errors:const promise = new Promise(function(resolve, reject) { // Rejecting a promise. reject("Rejected"); }); promise .then(function() { console.log("Fulfilled"); }) .catch(function(err) { console.log(err); }); // Output: Rejected
Remember that then
and the catch
methods immediately return a Promise
, allowing us to chain calls to other promise methods, for example:
const promise = new Promise(function(resolve) {
resolve("Promise Resolved!");
});
promise
.then(function(res) {
console.log(res);
})
.then(function() {
console.log("Chaining 1st promise");
})
.then(function() {
console.log("Chaining 2nd promise");
})
.then(function() {
console.log("Now throwing error in 3rd promise");
throw new Error("Error Thrown!");
})
.catch(function(err) {
console.log(err);
console.log("Error Caught!");
})
.then(function() {
console.log("Chained promise after catch");
})
/*
Output:
Promise Resolved!
Chaining 1st promise
Chaining 2nd promise
Now throwing error in 3rd promise
Error: Error Thrown!
Error Caught!
Chained promise after catch
*/
What is finally?
finally()
is used when we want to perform some processing or clean-up tasks. It executes once a promise is settled. Do read about this on mdn as well.
finally
on mdn: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally
Promise.all(), Promise.any(), Promise.allSettled() methods:
I highly recommend reading about all the mentioned methods on mdn docs, because they have provided a simple and wonderful explanation of all these methods(links provided after this table), there are several other methods as well. Summarizing the important information about a few of them here:
💡 Notice the usage of words fulfilled/settled.
Promise.all() | Promise.any() | Promise.allSettled() | |
Method Type | static method | static method | static method |
Paramters | an iterable | an iterable | an iterable |
Fulfillment Condition | Fulfills if all fulfilled, else rejects | Fulfills if any fulfills, rejects if all get rejected | Fulfills once all settled |
Fulfillment / Settlement Values | Fulfilled values of individual promise | Fulfilled value of the first fulfilled promise | Settled values of all the promises |
Return Value | A promise which is, |
1. Already fulfilled, if an iterable passed is empty.
2. Asynchronously fulfilled, if the iterable contains any pending promise or even if an iterable doesn't contain a pending promise but is non-empty.
3. Asynchronously rejected, if any of the promises are rejected. | A promise which is,
1. Already rejected, if an iterable passed is empty.
2. Asynchronously fulfilled, if any of the promises in the given iterable are fulfilled.
3. Asynchronously rejected, if all the promises are rejected. | A promise which is,
1. Already fulfilled, if an iterable passed is empty.
2. Asynchronously fulfilled, if all the promises in the given iterable are settled. |
mdn links:
Promise.all(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Promise.any(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/any
Promise.allSettled(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
That's all for this article. I hope it somehow made it a little simpler for you to understand promises.
Thanks! :)