Promise

May 20, 2023

A Promise is an object that represents a value that may not be available yet, but will be resolved at some point in the future. The purpose of a Promise is to provide a way to handle asynchronous operations in JavaScript.

Usage

Promises are commonly used when working with asynchronous operations such as fetching data from a server or reading a file from disk. In the past, developers had to use callbacks to handle these types of operations, which could lead to callback hell and make the code hard to read and maintain.

With Promises, developers can chain together multiple asynchronous operations and handle errors in a more readable and maintainable way. Promises provide a clean, declarative syntax that makes it easy to reason about code that deals with asynchronous operations.

Creating a Promise

To create a Promise, you use the Promise constructor. The constructor takes a single argument, a function called the executor function. The executor function should take two arguments, resolve and reject. The resolve function is called when the Promise is fulfilled with a value, while the reject function is called when the Promise is rejected with an error.

const promise = new Promise((resolve, reject) => {
  // do some asynchronous operation
  // if the operation is successful, call `resolve` with the result
  // if the operation fails, call `reject` with the error
});

Chaining Promises

One of the key benefits of Promises is the ability to chain multiple asynchronous operations together. When you chain Promises, each Promise in the chain returns a new Promise, which allows you to perform additional operations on the result of the previous Promise.

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => {
    // do something with the data
  })
  .catch(error => {
    // handle the error
  });

In the example above, the fetch function returns a Promise that resolves to the response from the server. We then call the json method on the response to extract the data from the response body. The json method also returns a Promise, so we can chain another then method to handle the data.

If any of the Promises in the chain reject with an error, the catch method is called, allowing you to handle the error in a centralized location.

Resolving Multiple Promises

Sometimes you may need to perform multiple asynchronous operations in parallel and wait for all of them to complete before continuing. Promises provide a way to do this using the Promise.all method.

const promise1 = fetch('https://api.example.com/data1');
const promise2 = fetch('https://api.example.com/data2');
const promise3 = fetch('https://api.example.com/data3');

Promise.all([promise1, promise2, promise3])
  .then(responses => {
    const data1 = responses[0].json();
    const data2 = responses[1].json();
    const data3 = responses[2].json();
    // do something with the data
  })
  .catch(error => {
    // handle the error
  });

In the example above, we create three Promises using the fetch function to fetch data from three different endpoints. We then pass an array of Promises to the Promise.all method, which returns a new Promise that resolves to an array of the results of each Promise in the array.

Rejecting Promises

Sometimes an error can occur during an asynchronous operation, and you need to reject the Promise with an error. To reject a Promise, you call the reject function that was passed to the executor function.

const promise = new Promise((resolve, reject) => {
  // do some asynchronous operation
  if (error) {
    reject(new Error('An error occurred'));
  } else {
    resolve('The operation was successful');
  }
});

In the example above, we check for an error during the asynchronous operation, and if an error occurs, we call the reject function with a new Error object. If the operation is successful, we call the resolve function with the result.

Handling Errors

When a Promise is rejected with an error, you can handle the error using the catch method. The catch method takes a function that is called when the Promise is rejected.

const promise = new Promise((resolve, reject) => {
  // do some asynchronous operation
  if (error) {
    reject(new Error('An error occurred'));
  } else {
    resolve('The operation was successful');
  }
});

promise.catch(error => {
  // handle the error
});

In the example above, we create a Promise that may reject with an error. We then use the catch method to handle any errors that occur.