Understanding Promises in JavaScript

In this blog, I'll be explaining the concept of promises for beginners or anyone who wants to learn about it in a simple manner.
While learning about promises, I came across the following definition - "A Promise is a JavaScript object that can be used to deal with the result of an asynchronous operation". Now let's break this down to get some more clarity.
Suppose you're building a food ordering app and have a function, placeOrder(). Once this function is called, there can be three possibilities - the order is placed, due to some error the order isn't placed or we are still waiting for a response. Either way, you will need to handle these scenarios. Enter, promises.
States of a promise
As we just read, a promise can have the following three states :
- Pending : waiting for the response, i.e., the initial state
- Fulfilled : the desired operation was performed successfully
- Rejected : the operation failed due to some error
So in the above example, if our order is placed successfully (meaning the promise is fulfilled), we will get an object in return that could contain the details of the order placed. We can then use this object however we want to. Example -
placeOrder(orderDetails)
.then(
//function called on success of the promise
(res)=>{
console.log(res)
}
);
In the above code once the order is placed successfully a response is returned, which, we are printing on the console. The .then() method is called after the promise is fulfilled or rejected.
What if my promise is rejected?
In this case too, you can use the .then() method to handle the failure of the promise. This is because the .then() method can take in two parameters - a function called when promise is fufilled and another one which is called when promise is rejected. Here's how -
const handleSuccess = (res) => {
console.log("Order placed, here are the order details: ", res);
}
const handleFailure = (err) => {
console.log("Failed with the following error: ", err);
//it is optional to have this function
}
placeOrder(orderDetails)
.then(handleSuccess, handleFailure);
The second function is optional as the better way to handle errors is using the .catch() method.
placeOrder(orderDetails)
.then(handleSuccess)
.catch(err){
console.log("Failed to place order, here's why: ", err);
}
Why do we need promises?
If you were to implement the same operation without promises, using callback functions, you might end up going into something called a callback hell. This happens when you have multiple callbacks one inside the other, and the code becomes unmanagable. This is also referred to as the pyramid of doom. So, to avoid this situation we use promises, as they help us in managing multiple callbacks in order without getting stuck.
Another thing to note is that JavaScript does not wait for asynchronous operation to be completed before moving on to synchronous operations. Hence, if we want the execution of a particular code block to wait while our asynchronous operation (of placing the order) is completed, before moving on to the next operations, we can do it using promises. Meaning only after our request is completed (i.e., either fulfilled or rejected), the following block of code will be executed.
Now hopefully, the original definiton of promises we came across might make more sense - "A Promise is a JavaScript object that can be used to deal with the result of an asynchronous operation".
Things to remember :
- Promises help us manage multiple callbacks and also handle errors in a better way.
- Using promises, we can handle asynchronous operations and their results.
.then()and.catch()are methods of promises. They are also called promise consumers.- Using only callback functions without promises, can lead to the callback hell.
Hope you were able to grasp this concept, do reach out if you find any issues :)