Promises are a nice feature of modern Javascript. In fact, if you use axios to make requests to your server, you are already using them. However, I see many people using promises without a good understanding of them. Today we change that, with this Javascript Promises Tutorial. Here we will learn what they are, how to use them, and how to create your own. Furthermore, we start from scratch, making things really simple.
Promises, a quick hands-on
We already mentioned axios. Axios is a library to make HTTP and HTTP requests in the form of Promises. Thus, if we use it, we know what to do with a promise. Let’s have a look (note that you need to install axios with npm in your project).
axios.get('/a/web/url')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
This is simple: we try to get a resource at the /a/web/url location. Once we obtain the resource, axios will call the then function. Instead, if axios fail to obtain the resource, it will call the catch function. In this example, we write to the console the response in case of success, or the error in case of failure. You can see here that promises are a clean way of implementing asynchronous functionalities. However, they don’t need to be asynchronous.
Javascript Promises Tutorial
The Jargon
Before we dive into our Javascript Promises Tutorial, it is better to have some jargon at hand. A promise is also known as thenable, because it has a then method. Furthermore, a promise can be in two states:
- Fulfilled – the action in the promise succeeded
- Rejected – the action in the promise failed
If the promise is not fulfilled nor rejected yet, we call it pending. Instead, once it either succeeds or fails, we call it settled. Remember that a promise can only settle once. In other words, the code you have in your then and catch will run just once.
Promises are a neat way to handle events. They evaluate correctly even if the event happened earlier.
Promises are a neat way to handle events because you don’t need to attach a listener. In plain Javascript, we use to add a listener to an object to trigger an event. However, our listener will actively wait for the event only after we created the listener. If the event happens before that, we just miss it. With promises, we don’t have to deal with this problem. In fact, the promise evaluates correctly even if the event happened beforehand.
Our first Promise
Now, that’s the part of this Javascript Promises Tutorial where we get our hands dirty. Creating a promise is very simple, you only need a Promise object. The constructor accepts a function as an argument. This function is the place where you put the logic of the Promise, possibly async. Thus, that function will accept two parameters: resolve and reject. Those two are also two functions, the ones you need to call if you consider the promise succeeded or failed.
var promise = new Promise(function(resolve, reject) {
// do your stuff here ...
if (/* everything was ok */) {
resolve("Good! :)")
}
else {
reject(Error("Did not work :("))
}
})
Now, when we use the then or catch on our promise, we are simply providing a resolve and reject function. Here is how we can use our promise.
promise.then(function(result) {
console.log(result)
}).catch(function(err) {
console.log(err)
})
In the then, we are logging Good! :), while in the catch we are logging Did not work :(. The then method may also take two arguments. In that case, the second is the catch function. However, the following code is not equivalent to the one above.
promise.then(function(result) {
console.log(result)
}, function(err) {
console.log(err)
})
The difference is hard to spot but extremely useful. We can see it in the following section.
Then, Catch, and chaining promises
As the last part of this Javascript Promises Tutorial, we want to understand the difference between .then(f1, f2) and .then(f1).catch(f2). This allows us to play funny things with promises, like chaining them with one another.
When we have a rejection, a promise will always skip to the next then statement. This means that with .then(f1, f2) we are sure we execute either f1 or f2, but never both. Instead, with .then(f1).catch(f2), we execute only f1 in case of success, but both f1 and f2 in case of failure.
This way, you can also chain promises. Below, a common approach of doing that.
promise.then(function(result) {
// Do this in case of success
}).catch(function(err) {
// Do this in case of error
}).then(function() {
// Always do this in the end
})
Wrapping it up
In this Javascript Promises Tutorial, we saw how to use promises and then how to create one. Now, we can handle events in a modern and beautiful way, very important in our async world. Here are the key concepts to take with you from this article.
- Create your promise with new
var promise = Promise(function(resolve, reject) { /* code here */ }). In the body of the function, callresolveif your logic succeeded orrejectif the logic failed. - Once you have a promise, provide it the resolve and reject function like this
promise.then(resolveFunction).catch(rejectFunction).
What do you think about promises? Are you using them instead of simple events in all parts of your application? Let me know your opinions in the comments!