Promises

  • This lesson covers how Promises simplify asynchronous programming.
  • Introduction to Promises

    In real-world JavaScript applications, many tasks take time to complete, such as:

    • Fetching data from a server

    • Reading files

    • Calling APIs

    • Waiting for a response

    • Performing background tasks

    JavaScript handles these tasks using asynchronous programming.

    Promises are one of the most important tools in JavaScript to manage asynchronous operations in a clean and readable way.

    Promises

    What Is a Promise ?

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

    Simple definition:

    A Promise is a guarantee that a value will be returned in the future — either successfully or with an error.

    Real-Life Analogy

    Think of ordering food online:

    • You place an order (promise is created)

    • Food is being prepared (pending)

    • Food delivered (fulfilled)

    • Order canceled (rejected)

    States of a Promise

    A Promise can be in one of three states:

    1. Pending

      • Initial state

      • Operation is still in progress

    2. Fulfilled

      • Operation completed successfully

      • Result is available

    3. Rejected

      • Operation failed

      • Error is returned

    Once a promise is fulfilled or rejected, its state cannot be changed.

    Creating a Promise

    Syntax

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

      // asynchronous operation

    });

    • resolve() → called when task succeeds

    • reject() → called when task fails

JavaScript Promise Basic Example

This code demonstrates a basic Promise that resolves or rejects based on a condition (success).

let promise = new Promise(function (resolve, reject) {
  let success = true;

  if (success) {
    resolve("Task completed successfully");
  } else {
    reject("Task failed");
  }
});

JavaScript Promise Handling with then and catch

This code demonstrates how to handle a Promise result using .then() for success and .catch() for errors.

promise
  .then(function (result) {
    console.log(result);
  })
  .catch(function (error) {
    console.log(error);
  });
  • How Promise Execution Works (Step-by-Step)

    1. Promise is created

    2. Promise state is pending

    3. Async task runs

    4. resolve() or reject() is called

    5. .then() handles success

    6. .catch() handles error

JavaScript Promise with Async Delay

This code demonstrates a Promise that resolves after a delay using setTimeout, and handles the result using .then().

let myPromise = new Promise(function (resolve, reject) {
  setTimeout(function () {
    resolve("Data received");
  }, 2000);
});

myPromise.then(function (data) {
  console.log(data);
});
  • Why Promises Are Needed

    Before promises, JavaScript used callbacks heavily, which caused problems like:

    • Deep nesting

    • Hard-to-read code

    • Difficult error handling

    This problem is called Callback Hell.

JavaScript Nested setTimeout Example

This code demonstrates nested setTimeout calls to execute asynchronous tasks in a delayed sequence.

setTimeout(function () {
  setTimeout(function () {
    setTimeout(function () {
      console.log("Done");
    }, 1000);
  }, 1000);
}, 1000);
  • Promises help avoid this.

    Promise Chaining

    What Is Promise Chaining ?

    Promise Chaining means executing multiple asynchronous operations one after another, where each operation depends on the result of the previous one.

    This is done using multiple .then() calls.

JavaScript Promise Chaining Example

This code demonstrates Promise chaining where each .then() returns a new value that is passed to the next step in the chain, with .catch() handling errors.

promise
  .then(function (result) {
    return newValue;
  })
  .then(function (newResult) {
    return anotherValue;
  })
  .catch(function (error) {
    console.log(error);
  });
  • Each .then() returns a new promise.

JavaScript Promise Chaining with Value Transformation

This code demonstrates how Promise chaining passes and transforms values step-by-step through multiple .then() handlers.

let promise = new Promise(function (resolve, reject) {
  resolve(10);
});

promise
  .then(function (value) {
    console.log(value);
    return value * 2;
  })
  .then(function (value) {
    console.log(value);
    return value * 2;
  })
  .then(function (value) {
    console.log(value);
  });

JavaScript Promise Chaining with Async Steps

This code demonstrates chaining multiple Promises where each step runs asynchronously and passes its result to the next step.

function stepOne() {
  return new Promise(function (resolve) {
    setTimeout(() => resolve("Step 1 completed"), 1000);
  });
}

function stepTwo(message) {
  return new Promise(function (resolve) {
    setTimeout(() => resolve(message + " → Step 2 completed"), 1000);
  });
}

stepOne()
  .then(function (result) {
    console.log(result);
    return stepTwo(result);
  })
  .then(function (finalResult) {
    console.log(finalResult);
  })
  .catch(function (error) {
    console.log(error);
  });
  • Error Handling in Promise Chaining

    If any promise in the chain fails:

    • Control jumps directly to .catch()

    • Remaining .then() blocks are skipped

JavaScript Promise Error Handling

This code demonstrates how errors thrown inside a Promise chain are caught and handled using .catch(), preventing further .then() execution.

promise
  .then(() => {
    throw new Error("Something went wrong");
  })
  .then(() => {
    console.log("This will not run");
  })
  .catch((error) => {
    console.log(error.message);
  });
  • Why Promise Chaining Is Important

    • Improves readability

    • Avoids nested callbacks

    • Centralized error handling

    • Easy to maintain and debug

    Common Mistakes

    • Forgetting to return a promise inside .then()

    • Writing logic inside nested .then() blocks

    • Not handling errors using .catch()

    • Mixing callbacks and promises incorrectly

    Best Practices for Using Promises

    • Always return a promise inside .then()

    • Use one .catch() at the end

    • Keep promise logic clean and simple

    • Avoid unnecessary promise creation

    • Prefer chaining over nesting

    Promises vs Callbacks (Quick Comparison)

    Feature

    Callbacks

    Promises

    Readability

    Poor

    Better

    Error handling

    Complex

    Simple

    Nesting

    Deep

    Flat

    Maintainability

    Hard

    Easy