A Promise in JavaScript is an object representing the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of it like ordering food at a restaurant: you get a buzzer (the promise) that will eventually notify you when the meal is ready (success) or if they ran out of ingredients (failure).

1. The Three States of a Promise

A Promise is always in one of these three states:

  1. Pending: Initial state; the operation hasn’t finished yet.
  2. Fulfilled (Resolved): The operation completed successfully.
  3. Rejected: The operation failed.

2. Creating a Promise

You create a promise using the new Promise constructor. It takes a function (executor) with two arguments: resolve and reject.

JavaScript

const myPromise = new Promise((resolve, reject) => {
  const success = true;

  setTimeout(() => {
    if (success) {
      resolve("Data fetched successfully!");
    } else {
      reject("Error: Could not fetch data.");
    }
  }, 2000); // Simulating a 2-second network delay
});

3. Consuming a Promise

Once a promise is created, you need to handle the result using .then(), .catch(), and .finally().

  • .then(): Runs when the promise is fulfilled.
  • .catch(): Runs when the promise is rejected.
  • .finally(): Runs regardless of the outcome (useful for cleanup).

JavaScript

myPromise
  .then((data) => {
    console.log(data); // "Data fetched successfully!"
  })
  .catch((error) => {
    console.error(error); // "Error: Could not fetch data."
  })
  .finally(() => {
    console.log("Operation finished.");
  });

4. Chaining Promises

One of the biggest advantages of Promises is the ability to chain them. This avoids “Callback Hell” (nested, unreadable code).

JavaScript
fetchUser(1)
  .then(user => fetchPosts(user.id))
  .then(posts => fetchComments(posts[0].id))
  .then(comments => console.log(comments))
  .catch(err => console.error("Error in the chain:", err));

5. Why Use Promises? (The “Callback Hell” Solution)

Before Promises, developers used nested callbacks. If you had to do three things in a row, the code would “pyramid” to the right, making it unreadable.

Callback Hell (Old way):

JavaScript

getData(function(a) {
  getMoreData(a, function(b) {
    getEvenMoreData(b, function(c) {
      console.log(c);
    });
  });
});

Promise Chaining (New way):

JavaScript

getData()
  .then(a => getMoreData(a))
  .then(b => getEvenMoreData(b))
  .then(c => console.log(c))
  .catch(err => console.log(err));

5. Modern Alternative: Async/Await

In modern JavaScript (ES8+), we use async and await to make asynchronous code look and behave like synchronous code. It is built on top of Promises.

JavaScript

async function displayData() {
  try {
    const data = await myPromise; // Waits for the promise to resolve
    console.log(data);
  } catch (error) {
    console.error(error); // Handles rejection
  }
}

displayData();

Categorized in:

Javascript,