JavaScript promises are simple 👌
Tags: javascript, asynchronous, promise, callbackfunction
Published: 2023-02-11 21:18:43

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 a **non-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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abcnhmksiwymeror61bf.png)

👉🏼 _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 of `setTimeout 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 of **non-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:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jec488zx537olgxldgsw.PNG)

Hint: we use `setTimeout function` inside `fetchDB function` to just simulate as if we are fetching data from a database.

It is time to execute these operations:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nlhvh5lwmtdpm1tdrmmw.PNG)

👉🏼 _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 invoked `fetchDB function` in statement number 20. But why it is "undefined"? because of the same reason `fetchDB function` has `setTimeout 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 functions `trimVideo` and `displayVideo `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.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/429z92vtgejlk9csdtk3.PNG)

`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 invoke `fn_1` function? You need to pass the function as an argument.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/81pvmlcbbnq8tul1ss8m.PNG)

👉🏼 _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?

The `trimVideo function` relies on the `fetchDB function`. We can rewrite `fetchDB function` to take function as an argument (callback function) which will be the `trimVideo function`. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5zfrlzehb1qh79pnzkl.PNG)

In addition, the `displayVideo function` relies on the `trimVideo function`.Thus, you can rewrite `trimVideo function` to take function as an argument (callback function) which will be the `displayVideo function`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a9wnt2ibla1ou653wy2j.PNG)

The `displayVideo function` will still the same as it is the final operation and there is no more operations depends on it.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f2kn6nu2rtyyztvmeroh.PNG)

Now how can we redefine the `main function`?

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5rwdhyvdeznnof2omu4h.PNG)

👉🏼 _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 found [here](http://callbackhell.com/).

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, <u>it has two main attributes or properties (state + result)</u> (Remember this for later discussion) . Let's dive deep and enjoy coding with promises.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/npxy6qxw1ng9g5e5jvwr.PNG)

As shown in the above code, to construct a promise you need to create an instance object from a predefined class `Promise` using `new` keyword. Writing `new 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 the `resolve function` or the `reject function`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1zigs2w31wkp4fvxfj0.PNG)

At the beginning of this section, we say that promise has two main attributes or properties** (state + result)**. 

Simply the **state** can be one of three states:
- pending
- fulfilled
- rejected

While the **result** is any value of any type which you pass to the `resolve` or the `reject` 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 has `then` property. `then` is just a function that takes another function as an argument.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/acj95daku44mdzapnwld.PNG)

The interesting here, that the arguments of this callback function is the result you previously sent through `resolve` function. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kjcgeon8x2twqr5cetbs.PNG)

In addition, any promise object has `catch` property. `catch` is just a function that takes another function as an argument.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgj6sqzo8igwyn4j4pwv.PNG)

The interesting here as well, that the arguments of this callback function is the result you previously sent through `reject` function. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3tbiyzavcper1p9vcp1c.PNG)

`then` and `catch` will never get invoked until the promise is fulfilled or rejected meaning that the `resolve` or the `reject` function must be invoked.

The last thing you need to know is that `then` function returns implicit `promise` by default. Implicit `promise` is a promise you didn't completely write, when you return any value 'X' from the callback function of `then` function, this value 'X' acts as a resolved result from a hidden `resolve` function. Thus, you can write a chain of `then` functions.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/45w0ig5f5xuzvyhszr2s.PNG)

Returning to our problem, _how can we use promises to handle our situation?_

JavaScript engine deals with this chain of `then` functions as one unit and doesn't execute any of them until the previous `then` 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 after `then` functions.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7em097ib3j943ljzh9w.PNG)

👉🏼 _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 👇: 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sdz6af3enbwm2a4wx5kn.PNG)

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 using `async/await` keywords. 👉 [Write promises chaining using async/await](https://dev.to/ayanabilothman/write-promises-chaining-using-asyncawait-3b1m) 👈 article will clarify the idea 😊.

Error handling of promises is a great topic. It will be clarified in another article, just wait for it 🔥.