Introduction

Asynchronous operations are a fundamental part of modern web development. JavaScript’s Promises provide a powerful way to manage and work with asynchronous code, making it more readable and maintainable. In this article, we will delve into Promises in JavaScript, explaining what they are and how to handle them effectively.

Understanding Promises

A Promise is an object representing the eventual completion or failure of an asynchronous operation. It provides a cleaner and more structured way to deal with asynchronous code compared to traditional callback functions.

Let’s consider a scenario where you, a student, have requested one of your friends to help with your homework. The friend has “promised” to help, though you cannot assure certainty to it since it is a future event. The friend may “fulfil” their promise as intended or “reject” it due to some unforeseen circumstances. Until you receive a rigid answer, the promise is in a “pending” state. This is the very essence of asynchronous programming. 

Promises are often used to handle data retrieval from servers, allowing you to work with the response data when it’s available. When reading or writing files, Promises help manage I/O operations asynchronously, ensuring the code doesn’t block while waiting for file access. Now, let’s dive into its implementation in JavaScript.

A Promise can be in one of three states:

Pending: Initial state, neither fulfilled nor rejected.

Fulfilled: The operation completed successfully, resulting in a value.

Rejected: The operation failed, resulting in an error.

Creating Promises

You can create a Promise using the Promise constructor, which takes a single function with two arguments: resolve and reject.

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

  // Asynchronous operation

  setTimeout(() => {

    const success = true;

    if (success) {

      resolve(‘Operation succeeded’);

    } else {

      reject(‘Operation failed’);

    }

  }, 1000);

});

Here, we create a Promise named myPromise that represents an asynchronous operation. Inside the Promise constructor, a setTimeout function simulates an asynchronous delay of 1 second. If the success variable is true after the delay, the Promise resolves with the message ‘Operation succeeded’ otherwise, it rejects with ‘Operation failed.’ The state and result of the Promise will be determined after the asynchronous operation is completed.

Handling Promises

Handling can occur directly after creating a Promise, in a sequence of chained Promises, or in response to specific events or conditions in your code, including interaction with a database, external programs, etc. To handle Promises, you typically use .then() and .catch() methods:

  • .then() method is used to specify what to do when a Promise is resolved
  • .catch() method is used to handle any errors (rejections)

Here’s how we handle a Promise which we have created. We attach .then() and .catch() blocks to the function that returns a Promise.

myPromise

  .then((result) => {

    console.log(result); // Output: “Operation succeeded”

  })

  .catch((error) => {

    console.error(error); // Output: “Operation failed”

  });

Expected output:

Operation succeeded

Chaining Promises

Promises can be chained to execute multiple asynchronous operations sequentially:

const firstPromise = () => {

  return new Promise((resolve) => {

    setTimeout(() => {

      resolve(‘First operation completed’);

    }, 1000);

  });

};

const secondPromise = () => {

  return new Promise((resolve) => {

    setTimeout(() => {

      resolve(‘Second operation completed’);

    }, 500);

  });

};

firstPromise()

  .then((result) => {

    console.log(result); // Output: “First operation completed”

    return secondPromise();

  })

  .then((result) => {

    console.log(result); // Output: “Second operation completed”

  })

  .catch((error) => {

    console.error(error);

  });

This code defines two functions, firstPromise and secondPromise, each returning a Promise that resolves after a certain time delay. It then demonstrates Promise chaining.

  • firstPromise resolves after 1 second, logging “First operation completed.”
  • It then chains to secondPromise, which resolves after 0.5 seconds, logging “Second operation completed.”
  • If an error occurs in either Promise, it will be caught and logged using the .catch() block, but in this case, there are no errors.

Expected output:

First operation completed

Second operation completed