Javascript Promises can be challenging to understand. Therefore, I would like to write down the way I understand promises.
A Promise in short:
“Imagine you are a kid. Your mom promises you that she’ll get you a new phone next week.”
You don’t know if you will get that phone until next week. Your mom can really buy you a brand new phone, or she doesn’t.
That is a promise. A promise has three states. They are:
Let’s convert this to JavaScript.
The code is quite expressive in itself.
Below is how a promise syntax looks normally:
Now that we have the promise, let’s consume it:
Let’s run the example and see the result!
Demo: https://jsbin.com/nifocu/1/edit?js,console
Promises are chainable.
Let’s say you, the kid, promise your friend that you will show them the new phone when your mom buys you one.
That is another promise. Let’s write it!
Notes: We can shorten the above code by writing as below:
Let’s chain the promises. You, the kid, can only start the showOff
promise after the willIGetNewPhone
promise.
That is how you can chain the promise.
Promises are asynchronous. Let’s log a message before and after we call the promise.
What is the sequence of expected output? You might expect:
1. before asking Mom
2. Hey friend, I have a new black Samsung phone.
3. after asking mom
However, the actual output sequence is:
1. before asking Mom
2. after asking mom
3. Hey friend, I have a new black Samsung phone.
You wouldn’t stop playing while waiting for your mom’s promise (the new phone). That’s something we call asynchronous: the code will run without blocking or waiting for the result. Anything that needs to wait for a promise to proceed is put in .then
.
Here is the full example in ES5:
The demo code is workable in ES5 environments (all major browsers + NodeJs) if you include Bluebird promise library. It’s because ES5 doesn’t support promises out of the box. Another famous promise library is Q by Kris Kowal.
The demo code works out of the box because ES6 supports promises natively. In addition, with ES6 functions, we can further simplify the code with an arrow function and use const
and let
.
Here is the full example in ES6 code:
Note that all the var
are replaced with const
. All of the function(resolve, reject)
have been simplified to (resolve, reject) =>
. There are a few benefits that come with these changes.
ES7 introduced async
and await
syntax. It makes the asynchronous syntax easier to understand, without the .then
and .catch
.
Rewrite our example with ES7 syntax:
Why do we need promises? How did the world look before promises? Before answering these questions, let’s go back to the fundamentals.
Let’s take a look at these two examples. Both examples perform the addition of two numbers: one adds using normal functions, and the other adds remotely.
If you add the numbers with the normal function, you get the result immediately. However, when you issue a remote call to get the result, you need to wait, and you can’t get the result immediately.
You don’t know if you will get the result because the server might be down, slow in response, etc. You don’t want your entire process to be blocked while waiting for the result.
Calling APIs, downloading files, and reading files are among some of the usual async operations that you’ll perform.
You do not need to use promises for an asynchronous call. Prior to promises, we used callbacks. Callbacks are a function you call when you get the return result. Let’s modify the previous example to accept a callback.
Instead of adding the numbers one at a time, we want to add three times. In a normal function, we would do this:-
This is how this looks with callbacks:
Demo: https://jsbin.com/barimo/edit?html,js,console
This syntax is less user-friendly due to the deeply nested callbacks.
Promises can help you avoid deeply nested callbacks. Let’s look at the promise version of the same example:
With promises, we flatten the callback with .then
. In a way, it looks cleaner because there is no callback nesting. With ES7 async
syntax, you could further enhance this example.
Before you settle down with promises, there is something that has come about to help you deal with async data called Observables
.
Let’s look at the same demo written with Observables. In this example, we will use RxJS for the observables.
Observables can do more interesting things. For example, delay
add function by 3 seconds
with just one line of code or retry so you can retry a call a certain number of times.
You may read one of my RxJs posts here.
Familiarizing yourself with callbacks and promises is important. Understand them and use them. Don’t worry about Observables just yet. All three can factor into your development depending on the situation.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
This comment has been deleted
Thank you for the explanation! It really helped me to get basic knowledge how to use promises and modern async/await keywords. Thank you a lot!