DEV Community

Abimanyu P
Abimanyu P

Posted on

Promises In JS

Promises in JavaScript

When JavaScript performs an operation that takes some time, such as fetching data from a server, it does not want to wait and block the rest of the program. Instead, JavaScript can handle the operation asynchronously.

A Promise is an object that represents the eventual result of an asynchronous operation. In simple words, a Promise means "I don't have the result right now, but I will give you the result later."

Creating a Promise

We can create a Promise using the built-in Promise constructor:

const result = new Promise((resolve, reject) => {

    const age = 10;

    setTimeout(() => {

        if (age >= 18) {
            resolve("You are eligible to vote");
        }

        else {
            reject("You are not eligible to vote");
        }

    }, 3000);

});
Enter fullscreen mode Exit fullscreen mode

Here, Promise is a built-in JavaScript constructor, and new Promise() creates a new Promise object.

The function passed to new Promise() is called the executor function:

(resolve, reject) => {
    // code
}
Enter fullscreen mode Exit fullscreen mode

resolve and reject are parameters of this executor function. The Promise constructor provides functions as arguments for these parameters.

We call resolve() when the operation is successful and reject() when the operation fails.

resolve("You are eligible to vote");
Enter fullscreen mode Exit fullscreen mode

means the operation was successful.

reject("You are not eligible to vote");
Enter fullscreen mode Exit fullscreen mode

means the operation failed.

Promise States

A Promise has three possible states:

State Meaning
Pending The operation is still in progress
Fulfilled The operation completed successfully
Rejected The operation failed

In our example, when the Promise is created, it is initially pending.

After 3 seconds, the age is checked. Since the age is 10, the condition is false and reject() is called.

So the Promise changes from:

Pending
   ↓
Rejected
Enter fullscreen mode Exit fullscreen mode

If the age were 18 or above, resolve() would be called instead:

Pending
   ↓
Fulfilled
Enter fullscreen mode Exit fullscreen mode

Handling a Promise

After creating the Promise, we can use .then() to handle a successful result and .catch() to handle an error.

const result = new Promise((resolve, reject) => {

    const age = 10;

    setTimeout(() => {

        if (age >= 18) {
            resolve("You are eligible to vote");
        }

        else {
            reject("You are not eligible to vote");
        }

    }, 3000);

})

.then((message) => {

    console.log(message);

})

.catch((error) => {

    console.log(error);

});
Enter fullscreen mode Exit fullscreen mode

When resolve() is called, the value passed to it is received by .then():

resolve("You are eligible to vote");
Enter fullscreen mode Exit fullscreen mode

The value "You are eligible to vote" becomes the argument passed to the .then() callback.

In:

.then((message) => {
    console.log(message);
})
Enter fullscreen mode Exit fullscreen mode

message is a parameter. It receives the value provided by the fulfilled Promise.

So the flow is:

resolve("You are eligible to vote")
              ↓
           .then()
              ↓
message = "You are eligible to vote"
              ↓
       console.log(message)
Enter fullscreen mode Exit fullscreen mode

Similarly, when reject() is called:

reject("You are not eligible to vote");
Enter fullscreen mode Exit fullscreen mode

the value is passed to .catch():

.catch((error) => {
    console.log(error);
});
Enter fullscreen mode Exit fullscreen mode

Here, error is a parameter that receives the rejected value.

The flow is:

reject("You are not eligible to vote")
              ↓
          .catch()
              ↓
error = "You are not eligible to vote"
              ↓
       console.log(error)
Enter fullscreen mode Exit fullscreen mode

Why Promises Are Useful

Promises are especially useful for handling asynchronous operations. For example, an application might need to:

  1. Get a user
  2. Get the user's orders
  3. Get the details of an order
  4. Make a payment

When many asynchronous operations depend on each other, using callbacks can result in deeply nested code called callback hell.

Promises allow us to chain these operations using .then():

getUser()
    .then(user => getOrders(user))
    .then(orders => getOrderDetails(orders[0]))
    .then(order => makePayment(order))
    .catch(error => {
        console.log(error);
    });
Enter fullscreen mode Exit fullscreen mode

Each .then() receives the result from the previous Promise and can return another Promise for the next operation.

This allows asynchronous operations to be written as a chain instead of deeply nested callbacks.

Conclusion

A Promise represents the eventual result of an asynchronous operation. It starts in a pending state and eventually becomes either fulfilled or rejected.

The important things to remember are:

  • Promise is a built-in constructor.
  • new Promise() creates a Promise object.
  • The function passed to new Promise() is called the executor function.
  • resolve and reject are parameters that receive functions from the Promise constructor.
  • resolve() is used when the operation succeeds.
  • reject() is used when the operation fails.
  • .then() handles a fulfilled Promise.
  • .catch() handles a rejected Promise.
  • Promises can be chained to make asynchronous code easier to manage.

The basic idea is:

        Promise
           ↓
       Pending
        ↙     ↘
   resolve   reject
      ↓         ↓
 Fulfilled   Rejected
      ↓         ↓
   .then()   .catch()
Enter fullscreen mode Exit fullscreen mode

Top comments (0)