Promise to Learn Promises in JavaScript
Tags: javascript
Published: 2020-06-12 15:39:23

 <link rel="canonical" href="https://medium.com/@codesprintpro/promises-deep-dive-in-javascript-ae83c4fc3b31" />

_Stuck with callback hell, here is the Promise Object which promises to solve the Callback Function Problems._

JavaScript is synchronous language by nature. The asynchronous functions like a callback, promise are internal to the JavaScript engine which is part of the browser. For example, Chrome uses the Google [V8](https://v8.dev/) JavaScript engine. Because of this, all the functionality related to asynchronous is developed in external libraries.

In JS we can solve asynchronous features using Callback, Promises, Async Await.

Before we start please read about [Callback Deep Dive in JavaScript](https://dev.to/sachinsarawgi/callback-deep-dive-in-javascript-3a1e).

### Topics Covered

-   What are Promises
-   Which Use Case Solved By Promises
-   Problem With Callback Functions, The Callback Hell
-   How To Write Promise Producer Code
-   Promise Object Properties
-   How To Write Promise Consumer Code
-   Solving Callback Hell With Promises
- ### What are Promises

Promises are JavaScript object introduced in ES6 onwards, which handles the asynchronous result of an operation.

It consists of producer code which produces a result/response after some duration of time from the time when it’s called. The other part is called consumer code which consumes the result/response generated by producer code.

### Which Use Case Solved By Promises

1.  Suppose we are calling an API, and that API response time is high. That means for processing the response we have to wait till we get the response.
2.  Suppose we are loading a JavaScript file in a function, and in the next line we are calling a function that is declared inside that script.
3.  Suppose you want to call another API once you get the first response, another one after you get a second API response. This type of requirement is called _callback chaining_.

If you know Callback functionality would seem similar based on the above scenario, indeed it is but there are some major problems with a Callback function which is handled by Promise very gracefully. One of them is called _Callback Hell,_ discussed in the next section_._

### Problem With Callback Functions, The Callback Hell

A callback function easy to understand when we don’t have callback chaining or callback after callback. Let’s take a simple example, where there is only one callback function

    function getAPIRequest(_callbackOnSuccess_, _callbackOnError_){  var getReq = new XMLHttpRequest();  
      getReq.open("GET", "https://reqres.in/api/users?page=2");  
      getReq.send();  
      getReq.onload = () => {  
        alert("The response is " + request.response);  
      }  
    }
    getAPIRequest();

In the above code, we called a GET API and once the response is received we are calling _processSuccessResponse_ method as a callback. It seems correct, but suppose we want to call the second API once we get the first API response, similarly the third API when we get the first API response. Let’s see it as an example, we will be calling the same API for now:

    function getAPIRequest(_callbackOnSuccess_, _callbackOnError_){    
      var getReq1 = new XMLHttpRequest();  
      getReq1.open("GET", "https://reqres.in/api/users?page=2");  
      getReq1.send();  
      getReq1.onload = () => {  
        alert("The response is " + request.response);  
        var getReq2 = new XMLHttpRequest();  
        getReq2.open("GET", "https://reqres.in/api/users?page=2");  
        getReq2.send();  
        getReq2.onload = () => {  
          alert("The response is " + request.response);  
          var getReq3 = new XMLHttpRequest();  
          getReq3.open("GET", "https://reqres.in/api/users?page=2");  
          getReq3.send();  
          getReq3.onload = () => {  
            alert("The response is " + request.response);  
            //another api call or some other processing  
          }  
        }  
      }  
    }
    getAPIRequest();

As we can see this thing can grow very large and it will become difficult to read, maintain the code, and understand if any issues come later on.

The promise is the answer to the above problem, it has consumer code that is kind of callback, and all consumers can be written separately and they will be executed one after another.

### How To Write Promise Producer Code

Promise producer code is the part that produces some result or output, which later can be processed by a consumer. Let’s try to call a GET API which is like our producer code and its result will the response which we are getting from the API.

    function getFirstAPIRequest() {  
      return new Promise(function(resolve, reject) {  
        var getReq = new XMLHttpRequest();  
        getReq.open("GET", "[https://reqres.in/api/users?page=2](https://reqres.in/api/users?page=2)");  
        getReq.send();  
        getReq.onload = () => {  
          if(getReq.status == 200){  
            resolve(getReq.response);  
          }else{  
            reject(new Error("There was some problem in the request."));  
          }  
        }  
      });  
    }

_Note_: Open [https://playcode.io/](https://playcode.io/) and paste this code. If you want to learn do practice with this code.

_The function passed to Promise is called executor, it runs automatically when the promise is created. The resolve and reject are callbacks provided by JavaScript itself._

When the executor gets the result we can call these callbacks depending on our requirement. Like in our case we called _resolve_ in case of response status is 200 else we are calling _reject_.

### Promise Object Properties

The Promise object created using the new keyboard has two properties _state_ and _result_.

![](https://cdn-images-1.medium.com/max/1600/1*k2euAUq6vkJeVvTNNOcCEQ.png)

They change their values as follows

-   _state_ will be pending at first, if _resolve_ is called it will change to _resolved state_ else if _reject_ is called it will change to _rejected state_.
-   _result_ will be undefined at first, _response_ when _resolve(response)_ is called else _error_ when _reject(error)_ is called.

![](https://cdn-images-1.medium.com/max/1600/1*UNw3kNwilaTwZ3w-5pZuQQ.png)

### How To Write Promise Consumer Code

If we want to consume response, we can do that in three ways in Promise using then, catch, and finally.

-   **then** Consumer Code

The _then_ method of Promise accepts two function arguments, the first one is executed when _resolve_ is called and the second one is executed when _reject_ is called.

    function getFirstAPIRequest() {  
      return new Promise(function(resolve, reject) {  
        var getReq = new XMLHttpRequest();  
        getReq.open("GET", "[https://reqres.in/api/users?page=2](https://reqres.in/api/users?page=2)");  
        getReq.send();  
        getReq.onload = () => {  
          if(getReq.status == 200){  
            resolve(getReq.response);  
          }else{  
            reject(new Error("There was some problem in the request."));  
          }  
        }  
      });  
    }
    getFirstAPIRequest()  
      .then((response) => console.log(response), (error) => console.log  
    ("Cannot process response"));

This will produce the following output.

![](https://cdn-images-1.medium.com/max/1600/1*yYfbLVLYlawxuzyaBVJR3A.png)

_If we only want to consume resolve callback we can remove second method definition:_

    getFirstAPIRequest()  
      .then((response) => console.log(response));
    
    _If we only want to consume reject callback we can pass null as the first argument and second any function definition._
    
    getFirstAPIRequest().then(null, (error) => console.log("Cannot process response"));

-   **catch** Consumer Code

_For handling reject callback promise has one special method called catch_. We can write our definition inside it, which will be called only in case when _reject_ callback is called.

    getFirstAPIRequest().catch((errorMsg) => console.log(errorMsg));

-   **finally** Consumer Code

_There may be some cases where we want to close some resources before completing the callback._ Then we use finally, it has only function definition (without any arguments) which will always be called. Once completed the execution will be passed to next function.

    getFirstAPIRequest()  
      .finally(() => console.log("Closing important resources))  
      .then((response) => console.log(response), (error) => console.log  
    ("Cannot process response"));

_Now suppose callback chaining case where we want to call another API on based on the response from the first API._ Let’s see an example:

    function getFirstAPIRequest() {  
      console.log("Processing first call");  
      return new Promise(function(resolve, reject) {  
        var getReq = new XMLHttpRequest();  
        getReq.open("GET", "[https://reqres.in/api/users?page=2](https://reqres.in/api/users?page=2)");  
        getReq.send();  
        getReq.onload = () => {  
          resolve(getReq.response);  
        }  
      });  
    }
    function getSecondAPIRequest(firstResponse) {  
      //do some processing on response, here I am passing the first simply  
      console.log("Processing second call");  
      return new Promise(function(resolve, reject) {  
        var getReq = new XMLHttpRequest();  
        getReq.open("GET", "[https://reqres.in/api/users?page=2](https://reqres.in/api/users?page=2)");  
        getReq.send();  
        getReq.onload = () => {  
          resolve(getReq.response);  
        }  
      });  
    }
    getFirstAPIRequest()  
      .then((response) => getSecondAPIRequest(response))  
      .then((response) => console.log(response));

This will produce the following output.

![](https://cdn-images-1.medium.com/max/1600/1*KYDUIoCDxVTl-9Loya58UQ.png)

I hope all the above examples will make you understand what Promise is in JavaScript, how it is better then Callback as it gracefully handles Callback Hell.

_Follow me over Medium for such articles  [@CodeSprintPro](https://medium.com/@codesprintpro)_