Let's Understand Promises in JavaScript
Tags: javascript, webdev, tutorial, frontend
Published: 2023-12-10 10:03:17

## What are Promises?

- Promise in Javascript is same as we commit a promise in real life. As we all know that promise is made for future, so definately, the outcome will also come in future, which makes the present state of promise is _pending_.

- Their are 2 Possible outcomes of a Promise, either the promise will _maintained_ or else it will be _broken_.

Similarly, In JavaScript, their are 2 possible outcomes of a Promise: _Resolve_ or _Reject_.

---

## Let's understand this statement with an example.

Suppose, You (Ram) and your friend (Sham) just passed Higher Secondary School and because you both are best friends, so you both decided take admission in the same college to do your bachelor's.

Now, there can be 2 possibility that:

- Ram and Sham took admission in same college, which means promise is fulfilled or in other words _Promise is Resolved_.
- Because of some reason Sham decided join his father's company directly after high school, which means promise which they made is broken or in other words _Promise is Rejected_.

---

## Different States of Promise in JavaScript

When a Promised is created in JavaScript, it is first initialised with a state of _pending._

1. Pending (Initial State, before the Promise succeeds or fails)
2. Resolved (Completed Promise)
3. Rejected (Failed Promise)


![Descriptive picture of promise states](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cb965rxbxn1g3r8hlfr3.png)

---

## What is the need of Promises?

So, Vivek tell me one thing why do we need promises in javaScript instead why can't we use callbacks to make async calls?

Okay, So the answer of your question is:

- We have _callback_ functions in JavaScript. But, a callback is not a special thing in JavaScript. It is a regular function that produces results after an asynchronous call completes (with success/error).
- While callbacks are helpful, there is a huge downside to them as well. At times, we may have one callback inside another callback that's in yet another callback and so on, now you're trapped in a _callback hell_. I'm serious! Let's understand this "callback hell" with an example.


```javascript
function displayMessage(fn){
   fn("inside displayMessage");

   setTimeout(() => {
     fn("1st work done!");

     setTimeout(() => {
        fn("2nd work done!");

        setTimeout(() => {
           fn("3rd work done!")
        },3000);

     }, 2000);

   },1000);

   fn("all works are done!!");
}

function onDone(statement){
  console.log(statement);
}

displayMessage(onDone);
```

So, Now lets understand the code line by line:

In this example a function displayMessage is called which recieves a callback function, this displayMessage functions does a simple work that it logs that status of work completions. As we can see that there is a nesting of setTimeout inside every setTimeout(), this nesting can go on, this nesting of function inside another function is called callback hell.
- Writing this type of code can create many production grade implication like: 
  - it makes the code performance slow, 
  - it impacts the readability of code, etc...


> _This is the reason why Promises are introduced_.

---

## Let's Understand how to write a Promise.

We have to create an instace of Promise class; Let's see how we can do that;

```javascript

let p = new Promise((resolve, reject) =>{
  // your code
})

```

The constructor function takes an executor function which takes two arguments which are _resolve_ and _reject_ repectively.

Whenever the promise is resolved successfully their after we call the resolve parameter with the result.
 ```javascript
 function myPromise(){
   let p = new Promise((resolve, reject) =>{
     setTimeout(() => {
       resolve("promise is resolved :)")
     }, 2000);
   });
   return p;
 }
 myPromise();
 ```

Whenever the promise is not resolved their after we call the reject parameter with a error.
 ```javascript
 function myPromise(){
   let p = new Promise((resolve, reject) =>{
     setTimeout(() => {
       reject("promise failed to resolved :(")
     }, 2000);
   });
   return p;
 }
 myPromise();
 ```

Now to get the output of the promise their are 2 methods: 

1. .then syntax
2. async/await syntax 

> let me tell you that async/await syntax is most prefered way to get the output of a Promise.

Let's us see how we can get the output using .then method

```javascript

function myPromise(){
  return new Promise((resolve, reject) =>{
    setTimeout(() =>{
      resolve("promise resolved :)")
    },2000)
  })
}

myPromise().then((data) =>{
  console.log(data);
})

```

```javascript
//output: 
  promise resolved :)
```

Here, while using this method .then takes a callback function which recives the data that is returned by the function. Inside that function we can perform any operation which is required by the program.

Let's us see how we can get the output using async/await method

```javascript

function myPromise(){
  return new Promise((resolve, reject) =>{
    setTimeout(() =>{
      resolve("promise resolved :)")
    },2000)
  })
}

async function getResult(){
  const data = await myPromise();
  console.log(data);
}


getResult();
```

```javascript
//output: 
  promise resolved :)
```

Here, while using async/await syntax we initialise an async function inside which we call the myPromise function with await keyword before it.

This await keywords stops the excetion further down the line until the promise is not resolved.

As soon as the promise is resolved we can perform any operation which we want, in this case we have logged the data.

---

## How errors are handled in promises

Both .then and async/await have different syntax for error handling.

First let's dig into .then() syntax.

Whenever we use .then() to consume the output of the promise we use .catch to handle the error.

Let's see how?

```javascript

// refering to above example
// if promise is rejected then .catch catches the error

myPromise().then((data) =>{
   console.log(data);
}).catch((error)=>{
  // whatever errror we get

  console.log(error);
})

```
using this way the error is handle.

But when we use Async/Await we write our code inside something known as try/catch block

```javascript

// refering to above example

const consumer = async () => {
  try{
    const data = await myPromise();
    console.log(data);
  } catch(error){
    // whatever errror we get
    console.log(error);
  }
}

consumer();
```

---

## Advantage over Promises over Callbacks

- **Better Readability**: Promises are a more structured and readable way of handling asynchronous operations. Promises allow you to chain multiple asynchronous operations together, Which makes the code more concise and clean as well as less bug-prone.
- **CallBack Hell**: Promises help you to avoid callback hell, which occurs when you have nested callbacks that can become more difficult to find out bugs and manage.
- **Error Handling**: Promises have built-in error-handling mechanisms to allow you to handle errors more easily.
- **Value return Ability**: Promises allow you to return a value from an asynchronous operation, That can be helpful when you try to pass data from one asynchronous to another.

---

> _Hope this article clears the topic_.
> _If you like this article then please like, share it on socials, comment your thoughts_.