More than Javascript core I have used the $.ajax
method provided by the jQuery library during web development and that is because everyone expects form submissions without page reloads these days. But there is a lot more to Javascript than just a few jQuery library functions, in fact, jQuery is just another Javascript library, but undisputedly the most useful one. Well, this article is not focused on jQuery so let's move on to the point.
Javascript was designed as a synchronous language, but callbacks made it function asynchronous, which was a great upgrade. Having said that, handling callbacks can become tedious at times. Promises could be utilized by using javascript libraries like Q, When, RSVP.js, etc, even jQuery had its own Deferred API providing the essence of overall promises. But finally, with ES6, Promises are now part of the standard javascript implementation and javascript developers couldn't be happier.
So let's start by understanding what a promise is and how we can implement and use it.
1. What is a Promise?
Just like human promises(where someone assures you of doing something), a promise in javascript is the assurance to fulfill a request, either successfully or unsuccessfully. To understand this in a better way, let's further break it down into what can happen when someone makes a promise in real life.
-
He or she will either fulfill the promise or fail to fulfill it.
-
If someone fulfills the promise, then we will expect something as a result of it, for example, if your father promises to gift you an iPhone on your birthday, then if he fulfills that promise successfully you will get an iPhone.
-
If someone fails to fulfill the promise, then again you expect some intimation about the same. Following up on the birthday gift example, if your father fails to gift you an iPhone, you expect a valid reason, right?
-
There can be a situation where the promise is not fulfilled at all, like when your father forgets about the birthday gift promise completely.
-
Also, at the time when a promise is made, we cannot assume the end result. But we sure can formulate actions to be performed if it fails or succeeds.
You will see that the points mentioned above have almost covered all the theoretical explanations of Javascript promises too with an example (Birthday gift from Father).
2. Creating a Promise in Javascript
A promise object represents something that is not available yet but will get resolved at some point in the immediate future. Let's take a real-world example before moving onto the code part; if you decide to use the promise API to make an asynchronous call to a web service, you will create a Promise
object which will represent the data that will be returned by the web service in future(typically after a few seconds). Also, we can attach callbacks to the Promise
object, which will be called once the data is available from the web service.
The following code shows how you can create a new Promise
object:
new Promise(function(resolve, reject) { ... });
or in the new syntax to write the executor function, we can also use the following code:
new Promise((resolve, reject) => { ... });
Here we are instantiating a new Promise
object and passing it a callback function. The callback function takes two arguments, resolve
and reject
, which are also functions. The asynchronous code will go inside the curly braces. If the asynchronous operations are successful then the result is returned by calling the resolve()
function and if some unexpected error occurs, the reason or the error message is passed on by calling the reject()
function.
Now let's create a promise to get a better overview:
var fulfillPromise;
fulfillPromise = true;
promiseExample = new Promise((resolve, reject) => {
if (fulfillPromise) {
resolve("I have fulfilled the Promise");
} else {
reject("I am sorry, I cant keep my word.");
}
});
console.log(promiseExample);
As we can see from the code above, we have made sure that our Promise gets successfully resolved and we have also specified the reolve() method which returns a string value. If you run this code and open the developer tools to observe the logs on the console, you will see this:
In the output we can see, it says PromiseStatus
as resolved and PromiseValue
holds the value returned from our resolve() function.
Before learning about the different statuses of the Promise let's lets re-run this code, but with fulfillPromise
as false
this time,
var fulfillPromise;
fulfillPromise = false;
promiseExample = new Promise((resolve, reject) => {
if (fulfillPromise) {
resolve("I have fulfilled the Promise");
} else {
reject("I am sorry, I cant keep my word.");
}
});
console.log(promiseExample);
We will get an Exception along with PromiseStatus
as rejected
and the value returned is the value from the reject()
function.
From the above two examples, now we have a basic understanding of Promise
. Now let's learn about the various statuses of Promise.
3. What is Promise Status?
PromiseStatus
represents the current status of the Promise
object. In the two examples above we have already witnessed resolved and rejected status values. There is one more possible value and that is pending.
We get the status value as pending when the Promise
object is still waiting for the asynchronous task to finish and return data.
Let's take an example for it. We will make our asynchronous task to wait using the setTimeout()
function before it resolves.
promiseExample = new Promise((resolve, reject) => {
setTimeout(function() {
resolve({
message: "I have fulfilled the Promise",
code: "Wohoo"
});
}, 10 * 1000);
});
console.log(promiseExample);
When we run this code, we will get the status of the Promise
object as pending
which will resolve successfully after 10 seconds.
Hence we can say that there are 3 possible statuses for a promise, they are:
-
pending
-
resolved
-
rejected
Apart from the status value, in the example above you should also notice that we have returned a JSON string from the resolve()
function, which is just to showcase another way of returning data.
4. Promise object Methods
Promise object has two types of methods:
-
Static methods, which can be used independently
-
Prototype methods, which must be applied to the instances of Promise
object
So let's first dive into the prototype methods.
4.1. Prototype Methods
There are 3 different prototype methods which are enough to handle all the basic requirements around Promise
object use cases. These methods also return Promise
object and are used to process the data after the asynchronous task completes and the call is either resolved or rejected.
1. then(onResolved, onRejected)
This method is called every time when a promise function call completes, either passed or failed. So, for both the callback functions resolve()
and reject()
, the next function executed is always then()
More or less, you should include the code for processing the returned data inside the function of then()
method. Following is the syntax for then()
method. It gets a callback function in it, which is executed.
promiseObject.then(function(value){ ... });
Once again, we would like to mention that this is called when the function's promise is resolved as well as when it is rejected.
2. catch(onRejected)
When a function's promise is rejected, in that case, if we have also defined the catch()
method, then then()
execution will be skipped and the function inside the catch()
will be executed. We all will agree that nothing is error-free and any piece of code can fail and lead to exceptions/errors. This method is to handle those exceptions/errors. Following is the syntax for it,
promiseObject.catch(function(){ ... });
3. finally(atTheEnd)
Once a function's promise is fulfilled, either resolved or rejected, then the function inside finally()
method is executed. So we can use it to do some common wrap up work in this method. Following is the syntax,
promiseObject.finally(function(){ ... });
4.2. Static Methods
There are 4 static methods in Promise
object. They are:
1. Promise.reject(reason)
This method enables you to directly create a rejected promise, for example:
var promise1 = Promise.reject("Not allowed”);
2. Promise.resolve(value)
This method helps you create a resolved promise directly, for example:
var promise2 = Promise.resolve("Welcome to Studytonight”);
3. Promise.All
When you are dealing with multiple function call returning Promise
objects and you want to continue only after you have received and analyzed all the Promise
objects, in that case, you can create an array of promises and then use the Promise
.All
method to check for resolved and rejected promises in the promise array and based on that perform some action. Let's have an example:
var arrayOfPromises = [];
arrayOfPromises.push(promiseObject1);
arrayOfPromises.push(promiseObject2);
arrayOfPromises.push(promiseObject3);
var finalPromise = Promise.All(arrayOfPromises);
// then we can have then() and catch() methods too
finalPromise.then(function(values) { ... });
finalPromise.catch(function(reason) { ... });
In the case of Promise
.All
once all the functions are executed and promise is fulfilled, based on the promises, if even one promise has been rejected, then Promise
.All
will return rejected promise. Only when all the promises are resolved in the array of promise, Promise.All
resolves.
4. Promise.race
This is somewhat similar to Promise
.All
, but in case of Promise.race
as soon as one promise is rejected, promise returned by Promise.race
is rejected. It will not even wait for the other function's promise objects to be resolved or rejected. As with Promise object, functions run parallelly, hence using Promise.race
can save time.
So this is all for this quick introduction tutorial about Promise in Javascript. If you have any doubts, share with us by posting your comment. In our coming articles, we will dig deeper into Promises.
More like this
Here are some more interesting articles related to JavaScript.