DEV Community

Cover image for JavaScript Promise
ABISHEK M
ABISHEK M

Posted on

JavaScript Promise

Introduction

In JavaScript, some operations take time to complete. For example, getting data from a server, calling an API, reading a file, or waiting for a timer.

JavaScript should not stop the entire program while waiting for these operations. This is where Promises are useful.

A Promise allows us to handle a result that will be available now, later, or after some time.

In simple words:

A Promise means, “I will give you the result later.”


What is a Promise?

A Promise is a JavaScript object that represents the eventual completion or failure of an asynchronous operation.

For example, when we request data from a server, we don't know exactly when the server will respond.

The Promise represents that future result.

let promise = new Promise((resolve, reject) => {
    // asynchronous operation
});
Enter fullscreen mode Exit fullscreen mode

A Promise mainly has three states:

  • Pending – The operation is still in progress.
  • Fulfilled – The operation completed successfully.
  • Rejected – The operation failed.

Promise States

              Promise
                 |
              Pending
              /     \
             /       \
       Fulfilled    Rejected
           ✅           ❌
Enter fullscreen mode Exit fullscreen mode

Once a Promise becomes fulfilled or rejected, it is called settled.


Why Do We Need Promises?

Some operations in JavaScript are asynchronous. They may take some time to complete.

Examples include:

  • API requests
  • Server communication
  • Database operations
  • File operations
  • Timers

For example, when we request information from a server, the response may take a few seconds.

Instead of blocking the program while waiting, JavaScript can continue doing other work and handle the result when it becomes available.

Promises provide a clean way to manage this process.


When Do We Use Promises?

Promises are mainly used when we need to work with asynchronous operations.

For example:

Request data from server
        ↓
      Promise
        ↓
    Wait for response
        ↓
   ┌────┴────┐
   ↓         ↓
Success     Failure
   ↓         ↓
 .then()   .catch()
Enter fullscreen mode Exit fullscreen mode

A common example is using the fetch() function to request data from an API.


How to Create a Promise

We can create a Promise using the Promise constructor.

let promise = new Promise((resolve, reject) => {

    let success = true;

    if (success) {
        resolve("Operation successful");
    } else {
        reject("Operation failed");
    }

});
Enter fullscreen mode Exit fullscreen mode

Here:

  • resolve() indicates success.
  • reject() indicates failure.

What is resolve()?

resolve() is used when an asynchronous operation is completed successfully.

resolve("Data received");
Enter fullscreen mode Exit fullscreen mode

It changes the Promise from:

Pending → Fulfilled
Enter fullscreen mode Exit fullscreen mode

What is reject()?

reject() is used when an operation fails.

reject("Something went wrong");
Enter fullscreen mode Exit fullscreen mode

It changes the Promise from:

Pending → Rejected
Enter fullscreen mode Exit fullscreen mode

Handling a Successful Promise with .then()

We use .then() to handle the successful result.

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

If the Promise is fulfilled, the value passed to resolve() is received by .then().

Example:

let promise = new Promise((resolve, reject) => {
    resolve("Data received successfully!");
});

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

Output:

Data received successfully!
Enter fullscreen mode Exit fullscreen mode

Handling Errors with .catch()

We use .catch() to handle a rejected Promise.

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

Example:

let promise = new Promise((resolve, reject) => {
    reject("Something went wrong!");
});

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

Output:

Something went wrong!
Enter fullscreen mode Exit fullscreen mode

.then() and .catch() Together

We can handle both success and failure using .then() and .catch().

let promise = new Promise((resolve, reject) => {

    let success = true;

    if (success) {
        resolve("Data received!");
    } else {
        reject("Failed to get data!");
    }

});

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

The flow is:

              Promise
                 ↓
              Pending
              /     \
             ↓       ↓
        resolve()  reject()
             ↓       ↓
          .then()  .catch()
             ↓       ↓
          Success   Error
Enter fullscreen mode Exit fullscreen mode

Real-World Example

Think about ordering food from a restaurant.

When you place an order, the food is not immediately ready.

Place Order
     ↓
Order is being prepared
     ↓
    Pending
     ↓
 ┌───┴────┐
 ↓        ↓
Ready    Cancelled
 ↓        ↓
Success  Failure
Enter fullscreen mode Exit fullscreen mode

This is similar to a Promise.

  • Pending → Food is being prepared.
  • Fulfilled → Food is delivered.
  • Rejected → Order failed or was cancelled.

This analogy helps us understand how a Promise represents a future result.


Promise Chaining

Sometimes we need to perform multiple asynchronous operations one after another.

Promises allow us to chain multiple .then() methods.

promise
    .then((result) => {
        return "Step 2";
    })
    .then((result) => {
        return "Step 3";
    })
    .then((result) => {
        console.log(result);
    })
    .catch((error) => {
        console.log(error);
    });
Enter fullscreen mode Exit fullscreen mode

This is called Promise chaining.

It helps us organize multiple asynchronous operations in a readable way.


Advantages of Promises

Promises provide several benefits:

1. Better handling of asynchronous operations

They provide a structured way to handle results that arrive later.

2. Error handling

.catch() provides a convenient way to handle errors.

3. Avoid callback hell

Promises can make multiple asynchronous operations easier to read and maintain.

4. Promise chaining

Multiple asynchronous operations can be connected using .then().


Promise vs Normal Synchronous Code

Synchronous code generally executes one operation after another.

console.log("First");
console.log("Second");
console.log("Third");
Enter fullscreen mode Exit fullscreen mode

Output:

First
Second
Third
Enter fullscreen mode Exit fullscreen mode

With asynchronous operations, JavaScript can continue executing other code while waiting for the operation to complete.

Promises help us handle the result when the asynchronous operation finishes.


Conclusion

Promises are an important part of modern JavaScript.

They are used to handle asynchronous operations such as API requests, server communication, timers, and other tasks that take time to complete.

The most important things to remember are:

Promise
   ↓
Pending
   ↓
 ┌───────────────┐
 ↓               ↓
Fulfilled      Rejected
 ↓               ↓
.then()        .catch()
Enter fullscreen mode Exit fullscreen mode

In simple terms:

A Promise represents the future result of an asynchronous operation.

Top comments (0)