Understanding JavaScript Promises👩‍💻👨‍💻
Tags: javascript, webdev, beginners, programming
Published: 2022-12-19 13:00:00

_Promises are one of the most important features of JavaScript, they allow us to write cleaner code by reducing callback functions and give us the ability to perform asynchronous operations in a more linear fashion.  Today, you are going to learn how promises work and how you can apply them in your code._ 

Let’s start, shall we? :) 

---

##What exactly is a  promise ?🧐 
A promise is an object that represents an asynchronous operation that hasn’t been completed yet, but is expected to provide a value sometime in the future. The promise object supports two properties: `State` and `Result`. 



###State & Result 
A promise object has three possible states: `Pending`, `Fulfilled` and `Rejected`. When an asynchronous operation starts, a promise is created and then goes in a `pending` (working) state.  While in a pending state, the result has no value; therefore is “**undefined**”.
 If the async operation is completed successfully, the promise switches to a `fulfilled` state with a value as result. If the operation fails, the state switches to `rejected` with a reason. 

####Good to know 📌
_A **fulfilled** value is passed on what we call an_ `onfulfilled` _callback and a **rejected** reason is passed on an_ `onrejected` _callback._




![Illustration of how promise works](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/05yln5uovj9x776xvqwb.gif)



##Are promises that useful? 🤔
Yes! Promises are handy in complex logic applications, they can easily handle multiple async operations and provide better error handling than callbacks. In short, they are the perfect choice for handling multiple callbacks at once.

####Good to know 📌
_If you ever find yourself having an unwieldy number of nested functions, so nested that it's mentally draining you, then you are probably in what we call the **Pyramid of Doom** also known as callback hell. At this point, you should probably think of using promises instead_ ;) 

Here is what the pyramid of doom looks like 👇

![Image of the pyramid of doom](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/apuk03xq7hcploglf8nz.png)

Alriight enough with technical terms, let's take a real-world example to understand promises more precisely and then jump to the coding part right after :)

---

**Real-world example** 🐤
Suppose, you place an online order for a rubber duck. The order will be created and will start processing. (In this case, a promise is created and is on `pending`)  

If the product is available, your order will get confirmed. (That's when the promise is resolved, in other words; `fulfilled`) 

If the product is out of stock, your order gets cancelled. (In this case, as you might've guessed, the promise is unfulfilled and as a result, it's `rejected`)

Are you still following? Great, now let's code this for a better perception ;) 

---

###Coding session 💻
Before we dive in, let's just take a look at how you can create a promise. There are a few ways in creating one but the most common way is using the `promise` constructor. Also known as the **executor function**, the `promise` will take a function as an argument. 

Example: 
```javascript
const promise = new Promise((resolve, reject) => {
   // Here is where the asynchronous operation starts.
      resolve('value');
}); 
```
What we did here was, create a promise that resolves with a value. In short, it is `fulfilled`. 

Can you guess on how we can create a promise that rejects with a reason? Common give it a shot ;)

**Here it is** 👇 
```javascript
const promise = new Promise((resolve, reject) => {
    // Start of the async operation 
    reject('reason');
});
```


####Good to know 📌
_You can also create a promise that is already resolved or rejected using the_ `Promise.resolve()` _and_ `Promise.reject()` _methods_.

**For example:** 
```javascript
const promise = Promise.resolve('value'); 

const promise = Promise.reject('reason');
```
Alright, now that you have an idea of how to create a promise, let's jump back to our real-world example :) 

---

**Back to our real-world example but with codes** 🐤

```javascript
//We are going to place an online order for our Rubber duck

function placeOrder(product) {
  return new Promise(function(resolve, reject) {
    if(product === 'Rubber Duck') {
      resolve('Confirmed order');
       }else { reject('Sorry your order has been cancelled');
    }
   })
  };
```
If your order is accepted, it will display the status of the order. If it's rejected, then that's probably the end of your code. 
 
 ```javascript
/* Let's assume your order has been accepted and display the status :) */ 

function orderStatus(order) {
    return new Promise(function(resolve) {
      console.log("Order is being processed");
        resolve(`Your ${order} has been delivered :)`);
     })
   };
```

---

###Promise Chaining ⛓

One of the advantages of promises is that they can be tied together. This will let you create a chain of async operations where the output of one operation is passed as the input to the next operation.
You can chain promises using the `Promise.then()` method.

For example:

```javascript
// Scenario with Chain promises

placeOrder('Rubber Duck').then(function(orderFromCustomer){
    console.log("Request received");
    let orderProcessed=orderStatus(orderFromCustomer);
    return orderProcessed;
}).then(function(orderProcessed){
    console.log(orderProcessed);
}).catch(function(error){
    console.log(error);
})
```

**Here is the whole code** 👇 

```javascript
//We are going to place an online order for our Rubber duck

function placeOrder(product) {
  return new Promise(function(resolve, reject) {
    if(product === 'Rubber Duck') {
      resolve('Confirmed order');
       }else { reject('Sorry your order has been cancelled');
    }
   })
  };

/* Let's assume your order has been accepted and display the status :) */ 

function orderStatus(order) {
    return new Promise(function(resolve) {
      console.log("Order is being processed");
        resolve(`Your ${order} has been delivered :)`);
     })
   };

// Scenario with Chain promises

placeOrder('Rubber Duck').then(function(orderFromCustomer){
    console.log("Request received");
    let orderProcessed=orderStatus(orderFromCustomer);
    return orderProcessed;
}).then(function(orderProcessed){
    console.log(orderProcessed);
}).catch(function(error){
    console.log(error);
})

// Output: Request received
//         Order is being processed
//         Your Confirmed order has been delivered :)
```

---

##Error Handling

Error handling helps in managing errors and helps the program to resume without being interrupted. In JavaScript, we use `Promise.catch()` to catch errors. It only handles errors that may happen between `.then()` methods.

**Perhaps an example might help :)**

```javascript
const promise = new Promise((resolve, reject) => {
    if(true) {
      resolve("It's workiiing!"); 
    } else { 
       reject("There is an error");
   } 
});

promise 
    .then(result => console.log(result))
    .then(result2 => {
         throw Error   // line 12
         console.log(result2);
}) 
    .catch(() => console.log('erroooor')); //last line

// Output: It's workiiing! 
//         erroooor
```

As you can see here, we've thrown an error on line 12 and normally, the program should've been interrupted. But the `.catch()` method on the last line was able to capture the error and log it to the console to make sure the program keeps running smoothly. (You can try to remove the last line and check if the program works)

---

##Async / Await

**Async/await** is a syntactic feature that allows us to write **asynchronous** code in a more similar way to a synchronous function.

The `Async` keyword is what lets the JavaScript engine know that we are declaring an async function.

The `await` keyword makes the function pause the execution and wait for a resolved promise before moving on to the next line of code.

**For example:**

```javascript
async function test() { 
    const value = await promise; 
// The code on this line will only be executed after the promise is resolved. 
}
```

Great, now one more thing☝️.

Async functions use `try/catch` statements for error handling.

**How does it work?**

Well, the code which we want to execute goes inside a try block and when performing that execution, if there is an error, it will go through the catch() block.

**Let's take a look :)**

```javascript
async function test() { 
    try { 
        const value = await promise; 
       } catch (error) { 
// The code on this line is executed if the promise is rejected. 
}}
```

---

##Conclusion

**Promises** are amazing! They are a core feature of JS that allows us to write async code more synchronously. Before promises, our code was full of confusing callback tricks and async.

They are ideal for managing multiple callbacks at once, error handling, executing async functions and many more.

---

###Hope you enjoyed this article ❤️

Greaat, that was quite a lot of codes, congrats to you if you made it so far! Feel free to bookmark this if you'd like to come back at it in the future.

Let me know if you enjoyed it by leaving a **like** or a **comment** :) or if there is a topic that you'd like me to write about in the future.

**Thanks for your time,**

**Happy coding and Merry Christmas✨🎄🎅**