What is a Promise?

A Promise is an object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. It’s used to handle asynchronous tasks more efficiently, providing cleaner, more readable code than callback functions.

A Promise can be in one of three states:

  • Pending: The promise is still in progress (neither fulfilled nor rejected).
  • Fulfilled: The promise has completed successfully with a result.
  • Rejected: The promise has failed with an error or reason.
const myPromise = new Promise((resolve, reject) => {
  // Simulating asynchronous operation
  let success = true;

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

What is PromiseState and PromiseResult?

  • PromiseState: This refers to the current state of a promise, which can be:

    1. Pending: The initial state, the promise is still being processed.
    2. Fulfilled: The operation completed successfully.
    3. Rejected: The operation failed, resulting in an error.
  • PromiseResult: This represents the value that the promise resolves to. It’s undefined when the promise is still in the “pending” state and becomes either the resolved value (if fulfilled) or the error message (if rejected).

const promise = new Promise((resolve, reject) => {
  resolve("Success");
});

console.log(promise);
// Output: Promise {<fulfilled>: 'Success'}
// Here, the PromiseState is "fulfilled", and the PromiseResult is "Success".

Promise Object is Immutable

Once a Promise is settled (either fulfilled or rejected), its result cannot be changed. This is known as the immutability of promises.

Even if you try to resolve or reject a promise again after it has already been settled, nothing will happen.

const promise = new Promise((resolve, reject) => {
  resolve("First value");
  resolve("Second value"); // This won't be executed
  reject("Error"); // This won't be executed either
});

promise.then((result) => console.log(result));
// Output: "First value"

What is Promise Chaining?

Promise chaining is the process of executing multiple asynchronous operations in a sequence, where each .then() handler returns a new promise, allowing further operations to be chained.

Each .then() method returns a new promise, allowing for the next .then() in the chain to execute after the previous one completes.

const promise = new Promise((resolve, reject) => {
  resolve(10);
});

promise
  .then((result) => {
    console.log(result); // 10
    return result * 2;
  })
  .then((result) => {
    console.log(result); // 20
    return result * 2;
  })
  .then((result) => {
    console.log(result); // 40
  });

Creating a Promise

You create a new promise using the Promise constructor, which accepts a callback function with two parameters: resolve (to fulfill the promise) and reject (to reject it).

const prom = new Promise((resolve, reject) => {
  let isValid = true;

  if (isValid) {
    resolve("Validation successful");
  } else {
    reject("Validation failed");
  }
});

prom
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });

.then() => .catch() => .then() => .then()

You can chain .then() and .catch() methods to handle promises step by step, including handling errors midway.

const prom = new Promise((resolve, reject) => {
  let condition = true;

  if (condition) {
    resolve("Step 1: Success");
  } else {
    reject("Step 1: Failed");
  }
});

prom
  .then((result) => {
    console.log(result); // "Step 1: Success"
    return "Step 2: Continue";
  })
  .catch((error) => {
    console.error(error); // This will be skipped if no error
    return "Step 2: Handle failure and continue";
  })
  .then((result) => {
    console.log(result); // "Step 2: Continue" (if no error) or "Step 2: Handle failure and continue"
    return "Step 3: Finish";
  })
  .then((result) => {
    console.log(result); // "Step 3: Finish"
  });