JavaScript Promises - Modern JS
Tags: javascript, tutorial, react, webdev
Published: 2022-11-06 15:00:00

In this article, we will learn about Promises in JavaScript with the help of some examples.

In JavaScript, Promises are beneficial for handling asynchronous operations. The Promise object represents an asynchronous operation's completion (or failure). It helps us find out if the asynchronous operation is successful or failed.

A JavaScript Promise is in one of these states:
- **Pending**: It is the initial state in which the promise is neither fulfilled nor rejected.
- **Fulfilled**: In this state, the promise is completed successfully.
- **Rejected**: In this state, the promise is rejected or failed due to any error.

The eventual state of a pending promise can be either fulfilled with a value or rejected with a reasonable error. The promise is settled if it is either fulfilled or rejected but not in a pending state.

&nbsp;
## Working

When a promise is created it is in a pending state, which means the process is not completed. If the process is completed successfully, the state is changed to fulfilled and if the process failed due to some errors, the state is changed to rejected.

You can think of a situation when you request data from a server it will be in a pending state. If the information is retrieved successfully, it will be in a fulfilled state otherwise it will be in the rejected state due to some errors.

&nbsp;
## Creating a Promise

Creating a Promise is straightforward, we use a `Promise()` constructor. The constructor takes a callback function as an argument. The function takes two functions as arguments i.e. `resolve()` and `reject()`. 

The `resolve()` function is called if the Promise is completed successfully. And the `reject()` function is called if some error occurs.

```js
let myPromise = new Promise(function(resolve, reject)
{
    // some producing code... (Code that may take some time)
});
```

&nbsp;
## Program with a Promise

Let’s take a look at a simple JavaScript program that checks if the candidate is eligible to vote or not by checking their age. Suppose the below program is asynchronous, so this is how we will handle it with a Promise.

```js
const age = 19;
let statusCheck = new Promise(function(resolve, reject)
{
    if (age >= 18)
    {
        // promise will be fulfilled if the condition is true
        resolve("Eligible to vote");
    }
    else 
    {
        // promise will be rejected if the condition failed
        reject("Not eligible to vote");
    }
})
console.log(statusCheck);
// Output: Promise { 'Eligible to vote' }
```

The above program creates a promise that takes two functions i.e. `resolve()` and `reject()`. `resolve()` is used if the process is successful and `reject()` is used if the process failed. 
The above program will be fulfilled if the age value is greater than or equal to 18 otherwise `reject()` function will be called and the output would be:
`Promise { <rejected> 'Not eligible to vote' }`

&nbsp;
## JavaScipt Promise Chaining

Promises are helpful to handle multiple asynchronous tasks, one after another. The methods `Promise.prototype.then()`, `Promise.prototype.catch()` and `Promise.prototype.finally()` are used to associate further actions with a promise that is settled. Also, these methods return promises that can be chained. 

### JavaScript .then() method

The `.then()` method takes two arguments; the first argument is a callback function for fulfilled case of the promise and second argument is a callback function for rejected case of the promise. Each `.then()` method returns a newly generated promise object that can be chained.

The syntax of `.then()` method,

```js
promiseObject.then(handleFulfilled, handleRejected);
```

It can be chained like this,

```js
promiseObject
    .then(handleFulfilledA, handleRejectedA)
    .then(handleFulfilledB, handleRejectedB)
    .then(handleFulfilledC, handleRejectedC)
```

JavaScript promise takes two arguments, for success and failure. Both are optional, so you can add only one or both of them. You can only add semicolon `;` after last `.then()` method otherwise it will break the chain.

```js
let chainedPromises = new Promise(function(resolve, reject)
{
    resolve("1. JavaScript Promise Resolved");
})

chainedPromises
    .then((result) => {
        console.log(result);
    })
    .then((result) => {
        console.log("2. Chaining in promises")
    })
    .then((result) => {
        console.log("3. Last method")
    })
```

**Output**

```
1. JavaScript Promise Resolved
2. Chaining in promises
3. Last method
```

Here each `.then()` method is returning a newly created promise object which is chained. The processing continues to next link even if any of the `.then()` lacks a callback function that returns a promise object which means that every rejection callback function is omitted until final `.catch()` method.

### JavaScript .catch() method

The `.catch()` method is same as `.then()` method without the slot for a callback function when promise is fulfilled successfully. It is used to handle rejected case of promise. For example,

```js
let chainedPromises = new Promise(function(resolve, reject)
{
    reject("1. JavaScript Promise Rejected");
})

chainedPromises
    .then((result) => {
        console.log(result);
    })
    .then((result) => {
        console.log("2. Chaining in promises")
    })
    .then((result) => {
        console.log("3. Last method")
    })
    .catch((result) => {
        console.log(result);
    })
```

**Output**

```
1. JavaScript Promise Rejected
```

In the above code only the `.catch()` method is executed because the promise is rejected. The `.catch()` method is used to handle the errors in a promise.

### JavaScript .finally() method

The `.finally()` method is used to define a code block to run regardless of the result. It schedules a callback function to be called when the promise is settled.

```js
let chainedPromises = new Promise(function(resolve, reject)
{
    resolve("1. JavaScript Promise Resolved");
})

chainedPromises
    .then((result) => {
        console.log(result);
    })
    .then((result) => {
        console.log("2. Chaining in promises")
    })
    .then((result) => {
        console.log("3. Last method")
    })
    .catch((result) => {
        console.log(result);
    })
    .finally(() => {
        console.log("4. The .finally() would always run in the end")
    })
```

**Output**

```
1. JavaScript Promise Resolved
2. Chaining in promises
3. Last method
4. The `.finally()` would always run in the end
```

The `.finally()` method would be called when the promise is settled regardless of the result (whether the promise is resolved or rejected). It is called when promise is not in pending state.

&nbsp;
## Callback vs Promises

Callback functions and Promises are same in a sense that both are used to handle asynchronous operations. While callbacks can also be used to handle synchronous operations.

**Callbacks**
- Syntax is difficult to understand
- Nested callbacks in one another creates a pyramid structure known as Callback Hell
- Error Handling gets complex
- For example,

```js
api1((result1) => {
    api2((result2) => {
        api3((result3) => {
            // code goes here...
            if (error)
            {
                // handle rejected state
            }
            else
            {
                // handle fulfilled state
            }
        })
    })
})
```


**Promises**
- Syntax is user-friendly and easy to read
- Error handling is easier to manage
- For example, 

```js
api1()
    .then(result1 => {
        return api2(); 
    })
    .then(result2 => {
        return api3(); 
    })
    .then(result3 => {
        // do something
    })
    .catch((error) => {
        // handle error
    })
```


&nbsp;
## Wrapping up!

That's all for this article, hope you learned something. Thanks for reading, catch you later!

You can show me love by buying me a coffee that would help me grow as an Opensource Dev :)

<a href="https://www.buymeacoffee.com/moazamdev" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 100px !important;" ></a>

---

{% user moazamdev %}