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, callresolve
if your logic succeeded orreject
if 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!