This article will be simple and only mentions basics related to promises in JavaScript and why we need them. Be ready and just read this story and enjoy understanding promises. 🤗.
👀Important to know that:
JavaScript is anon-blocking language. What does this mean? When JavaScript engine starts to run the code, it doesn't implement the statements in the order as you write them 🤔 "in some cases". So let's see how can this look like.
👉🏼After executing the above code the result will be:
I'm the first statement
I'm the third statement
I'm the second statement
And the reason behind this behavior is the usage ofsetTimeout function
which is an asynchronous function in JavaScript.
So,what is asynchronous function? 🤔
Simply, it's a function that may take some time. Thus, JavaScript engine holds the execution of it and runs the rest of the code. After finishing all non-asynchronous statements, it finally executes this postponed asynchronous function.
This is the exact meaning ofnon-blocking language, this behavior of holding on the execution of some code written at certain order and be able to execute it later.
Problem definition😓:
Why this non-blocking behavior can be an issue in some cases? What if you need to do some operations ("b" & "c") which depends on another operation "a" that can take some time? 👇
Now let me introduce an interesting case study 🤓.
We need to fetch a video from a database, but this operation can take some time due to internet connection or for any other reasons. After receiving the video, we need to trim it. The last thing we need is to display the trimmed video.
So now we have three operations:
a- Request the database to fetch the video.
b- Trim the received video.
c- Display the trimmed video.
As you see, the three operations depend on each other, you can't trim or display the video until you receive the original one.
Let's define the functions to do each single operation:
Hint: we usesetTimeout function
insidefetchDB function
to just simulate as if we are fetching data from a database.
It is time to execute these operations:
👉🏼After executing the above code the result will be:
undefined After trim. And here is the final video to display!
Notice that the first word is "undefined". This value is the result of invokedfetchDB function
in statement number 20. But why it is "undefined"? because of the same reasonfetchDB function
hassetTimeout function
which will take some time. So the engine skips it and in turns it will return nothing, so the value will be undefined.
Since all other functionstrimVideo
anddisplayVideo
depend on the original video so they won't return the expected result.
What is the solution then?
Solution 1 🙌: Callback functions
To handle this, we can use callback functions.What is a callback function? It's a function that is a parameter of another function.
fn_1
is a simple regular function. What if it takes a parameter? this parameter can be of any type even if it was a function.
How can you invokefn_1
function? You need to pass the function as an argument.
👉🏼After executing the above code the result will be:
f1
f2
So now returning to our case, how you use callback functions to successfully execute all operations related to the required video?
ThetrimVideo function
relies on thefetchDB function
. We can rewritefetchDB function
to take function as an argument (callback function) which will be thetrimVideo function
.
In addition, thedisplayVideo function
relies on thetrimVideo function
.Thus, you can rewritetrimVideo function
to take function as an argument (callback function) which will be thedisplayVideo function
.
ThedisplayVideo function
will still the same as it is the final operation and there is no more operations depends on it.
Now how can we redefine themain function
?
👉🏼After executing the above code the result will be:
Here is the video. After trim. And here is the final video to display!
Finally, we got the expected results. But it seems that this is a complex code, doesn't it? What we did here is when we invoke the functions, each function that takes callback function added complexity to the code. And this is known as callback hell. Writing nested callback functions is so hard and complex.
More details on callback hell can be foundhere.
Are there any alternative solutions to avoid using callback functions and simplify the code writing? Yes, thanks to ES6.
Solution 2 🙌: Promises
I know you read a lot to reach here, but the reason behind using promises will help you well understand why promises are so valuable.
What is a promise? Promise is a special object in JavaScript,it has two main attributes or properties (state + result) (Remember this for later discussion) . Let's dive deep and enjoy coding with promises.
As shown in the above code, to construct a promise you need to create an instance object from a predefined classPromise
usingnew
keyword. Writingnew Promise()
will create a promise object.But what is the function inside those round brackets?
(resolve, reject)=>{}
is a function which has two arguments(resolve, reject)
, you can rename them anything else, but by convention they're called resolve and reject.
And now what are those resolve and reject? 🤔 They are two callback functions "but don't worry we won't write here anymore callback functions😅. We just need to understand what we write while constructing a promise". As you knew before, when you write a function as an argument you can call this function whenever you want inside the parent function.
And this exactly what happens.When should you call these functions?
you should invoke the
resolve function
when you need to return a value if your code has executed in an expected manner.Otherwise, you should invoke the
reject function
to return a value if your code failed or an error occurred.
Knowing that, only one function got invoked. If you try to invoke both functions after each other without any conditions. Only the first one will be invoked either it was theresolve function
or thereject function
.
At the beginning of this section, we say that promise has two main attributes or properties** (state + result)**.
Simply thestate can be one of three states:
- pending
- fulfilled
- rejected
While theresult is any value of any type which you pass to theresolve
or thereject
functions when you invoke them.
Results depend on the states. if the state was fulfilled, resolve function get invoked with the result. And when the state was rejected, reject function get invoked with the result.
But _what is a pending state? 🤔 It is the state of the promise which hasn’t been fulfilled nor rejected yet. This state has no results you can deal with.
Ok, you now understand what is promise. The final question,how can it help you?
Any promise object hasthen
property.then
is just a function that takes another function as an argument.
The interesting here, that the arguments of this callback function is the result you previously sent throughresolve
function.
In addition, any promise object hascatch
property.catch
is just a function that takes another function as an argument.
The interesting here as well, that the arguments of this callback function is the result you previously sent throughreject
function.
then
andcatch
will never get invoked until the promise is fulfilled or rejected meaning that theresolve
or thereject
function must be invoked.
The last thing you need to know is thatthen
function returns implicitpromise
by default. Implicitpromise
is a promise you didn't completely write, when you return any value 'X' from the callback function ofthen
function, this value 'X' acts as a resolved result from a hiddenresolve
function. Thus, you can write a chain ofthen
functions.
Returning to our problem,how can we use promises to handle our situation?
JavaScript engine deals with this chain ofthen
functions as one unit and doesn't execute any of them until the previousthen
function resolved. Which means that any code written inside this chain will be executed in the right order as you write and this is what we need.
In addition, the engine will execute those functions in asynchronous way. It won't block any code afterthen
functions.
👉🏼After executing the above code the result will be:
First statement out of promise
Second statement out of promise
4
Applying these concepts in our operations we can rewrite our code as the following 👇:
The difference between writing the code using promises and writing the code using the callback functions is so obvious. The code is more clear, simple and understandable now 🥳.
We can enhance the writing of promises and chains in some cases usingasync/await
keywords. 👉Write promises chaining using async/await 👈 article will clarify the idea 😊.
Error handling of promises is a great topic. It will be clarified in another article, just wait for it 🔥.
Top comments(3)
For further actions, you may consider blocking this person and/orreporting abuse