Promises — Understanding JavaScript API Requests and Responses in the Data Fetching lifecycle
Tags: javascript, node, webdev, programming
Published: 2023-05-01 09:17:44

---
title: Promises — Understanding JavaScript API Requests and Responses in the Data Fetching lifecycle
published: true
description: A powerful feature of JavaScript that makes it easier to write Asynchronous code.
tags: javascript, node, webdev, programming
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-05-01 09:13 +0000
---

![Promises](https://cdn-images-1.medium.com/max/2000/1*0xv_E34lF_dvwL_nbuTvaQ.png)

Before this article, I mentioned to you that I would start the articles series and I already created an Introduction, V8 JavaScript engine, Callbacks, AJAX and XMLHttpRequest, and about the Synchronous and Asynchronous. If you lost what I did, check it:

* [Introduction — Understanding JavaScript API Requests and Responses in the Data Fetching lifecycle](https://dev.to/rodcast/introduction-understanding-javascript-api-requests-and-responses-in-the-data-fetching-lifecycle-2f08)

* [V8 JavaScript engine — Understanding JavaScript API Requests and Responses in the Data Fetching lifecycle](https://dev.to/rodcast/v8-javascript-engine-understanding-javascript-api-requests-and-responses-in-the-data-fetching-lifecycle-1m6j)

* [Callbacks — Understanding JavaScript API Requests and Responses in the Data Fetching lifecycle](https://dev.to/rodcast/callbacks-understanding-javascript-api-requests-and-responses-in-the-data-fetching-lifecycle-41b9)

* [AJAX and XMLHttpRequest — Understanding JavaScript API Requests and Responses in the Data Fetching lifecycle](https://dev.to/rodcast/ajax-and-xmlhttprequest-understanding-javascript-api-requests-and-responses-in-the-data-fetching-lifecycle-4ap6)

* [Synchronous and Asynchronous — Understanding JavaScript API Requests and Responses in the Data Fetching lifecycle](https://dev.to/rodcast/synchronous-and-asynchronous-javascript-api-requests-and-responses-in-the-data-fetching-lifecycle-22b3)

*In this article, I’ll not explain the concept of Fetch API or Async/Await but don’t worry that I’ll explain it in the next article.*

[Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) are a way to handle asynchronous operations. Promises represent a value that may not be available yet but will be resolved at some point in the future. They provide a way to write asynchronous code that is easier to reason about and less prone to error.

A promise represents a future value that may be available now or later or may never be available at all.

A promise has three possible states:

*Pending:* The initial state, before the Promise is resolved or rejected.
*Fulfilled:* The Promise has been resolved with a value.
*Rejected:* The Promise has been rejected for a reason.

Promises can be created using the *Promise constructor*, which takes a function with two arguments: a *resolve function* and a *reject function*.

The *resolve function* is used to fulfill the promise with a value. If you have a successful result from your asynchronous operation, you pass that value to the resolve function.

The *reject function* is used to reject the promise with an error value. If you encounter an error during your asynchronous operation, you can pass the error value to the reject function.

Once a promise is created, you can use its then method to handle the *fulfilled *state and its catch method to handle the *rejected *state. You can also use the *finally *method to handle both states.

### How to make a Promise in JavaScript?

There are different types to create a Promise.

Promise object that is created using the Promise constructor.

```javascript
    // Created using the Promise Constructor
    const promise0 = new Promise((resolve, reject) => {
      // When the operation is complete, call either `resolve` or `reject`
    });
```

Promise object that is created using the Promise constructor, *new *keyword, and *resolve *function:

```javascript
    const promise1 = new Promise((resolve, reject) => {
      resolve("Resolved!");
    });
    
    promise1.then((result) => {
      console.log(result); // Output: Resolved!
    });
```

Promise object that is created using the Promise constructor, without *new *keyword (which is a shorthand way), and *resolve *function:

```javascript
    const promise2 = Promise.resolve("Resolved!");
    
    promise2.then((result) => {
      console.log(result); // Output: Resolved!
    });
```

Also, you can use *reject *function and the *catch *method:

```javascript
    const promise2 = Promise.reject("Rejected!");
    
    promise2
      .then((result) => {
        console.log(result);
      })
      .catch((error) => {
        // Output: Promise rejected with error: Rejected!
        console.error(`Promise rejected with error: ${error}`);
      });
```

Promise object that is created using the Promise constructor, new keyword, *resolve *and *reject* functions, as well as the *then*, *catch*, and *finally *methods:

```javascript
    const promise3 = new Promise((resolve, reject) => {
      // Create a random number between 1 and 5
      const randomNumber = Math.floor(Math.random() * 5 + 1);
    
      if (randomNumber >= 2) {
        resolve(randomNumber);
      } else {
        reject(new Error("Random number is less than 2"));
      }
    });
    
    promise3
      .then((result) => {
        // If the random number is between 1 and 2, output:
        // Promise resolved with result: `result` (result is the random number)
        console.log(`Promise resolved with result: ${result}`);
      })
      .catch((error) => {
        // If the random number is between 3 and 5, output:
        // Promise rejected with error: Random number is less than 2
        console.error(`Promise rejected with error: ${error.message}`);
      })
      .finally(() => {
        // Always after resolve or reject, output:
        // Promise completed
        console.log("Promise completed");
      });
```

Also, you can use a *try-catch block* to handle any errors that may occur during the execution of the Promise executor function. If an error occurs, we throw it and catch it in the *catch block*, where we *reject* the Promise with the error.

```javascript
    const promise3 = new Promise((resolve, reject) => {
      try {
        // Create a random number between 1 and 5
        const randomNumber = Math.floor(Math.random() * 5 + 1);
    
        if (randomNumber >= 2) {
          resolve(randomNumber);
        } else {
          throw new Error("Random number is less than 2");
        }
      } catch (error) {
        reject(error);
      }
    });
    
    promise3
      .then((result) => {
        // If the random number is between 1 and 2, output:
        // Promise resolved with result: `result` (result is the random number)
        console.log(`Promise resolved with result: ${result}`);
      })
      .catch((error) => {
        // If the random number is between 3 and 5, output:
        // Promise rejected with error: Random number is less than 2
        console.error(`Promise rejected with error: ${error.message}`);
      })
      .finally(() => {
        // Always after resolve or reject, output:
        // Promise completed
        console.log("Promise completed");
      });
```

There’s one good example of using the Promise object is creating a sleep function to add the delay before the data is returned:

```javascript
    const sleep = (ms) => {
      return new Promise((resolve) => setTimeout(resolve, ms));
    };
    
    // Delay of 5 seconds (5000 milliseconds) before the data is returned
    sleep(5000).then(() => {
      console.log("Lorem"); // Output: "Lorem"
    });
```

### What is Promise Chaining?

[Promise Chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#chaining) is a powerful technique in JavaScript that allows us to execute asynchronous operations in a specific order. This technique involves returning a new Promise from a *then()* callback of an existing Promise, which allows us to chain multiple asynchronous operations together.

```javascript
    const promise3 = (name) => {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          return resolve(name);
        }, 1000); // Delayed function after 1 second (1000 milliseconds)
      });
    };
    
    promise3("Lorem")
      .then((data) => {
        console.log(data); // wait 1 second and output: "Lorem"
        return promise3("Ipsum");
      })
      .then((data) => {
        console.log(data); // wait 1 second and output: "Ipsum"
        return promise3("Dolor");
      })
      .then((data) => {
        console.log(data); // wait 1 second and output: "Dolor"
        return promise3("Amet");
      })
      .then((data) => {
        console.log(data); // wait 1 second and output: "Amet"
      });
```

>  Async/await is a more readable and concise way of working with Promises than chaining Promises, especially when dealing with complex logic that involves multiple asynchronous operations, and I’ll explain it in the next article.

### What are and which are Promise combinators?

[Promise combinators](https://v8.dev/features/promise-combinators) are higher-order functions that operate on multiple Promises and return a new Promise that depends on the outcome of the input Promises, and one powerful technique using Promises is the ability to execute multiple asynchronous operations in parallel. This technique can improve performance and reduce the overall time it takes to complete multiple asynchronous operations.

Below are the Promise combinators available in JavaScript:

*Promise.all():* Returns a new Promise that resolves with an array of the *results of all input Promises*, in the same order as they were passed in. If any of the input Promises are *rejected*, the returned Promise is also *rejected *with the reason for the first *rejected *Promise.

```javascript
    Promise.all([promise1, promise2, promise3])
      .then((results) => {
        console.log("All Promises resolved:", results);
      })
      .catch((error) => {
        console.error("One or more Promises rejected:", error);
      });
```

*Promise.race():* Returns a new Promise that is settled with the result of the *first input Promise to settle*, either *resolved *or *rejected*.

```javascript
    Promise.race([promise1, promise2, promise3])
      .then((result) => {
        console.log("The first Promise settled:", result);
      })
      .catch((error) => {
        console.error("One or more Promises rejected:", error);
      });
```

*Promise.any():* Returns a new Promise that resolves with the value of the *first input Promise to resolve*. If all input Promises are *rejected*, the returned Promise is also *rejected *with an *AggregateError *that contains an array of the rejection reasons.

```javascript
    Promise.any([promise1, promise2, promise3])
      .then((result) => {
        console.log("The first Promise resolved:", result);
      })
      .catch((error) => {
        console.error("All Promises rejected:", error);
      });
```

*Promise.allSettled():* Returns a new Promise that resolves with an array of objects representing the outcomes of *all input Promises*, whether they were resolved or rejected. Each object has a status property that is either *fulfilled *or *rejected*, and a value or reason property that contains the resolved value or rejection reason, respectively.

```javascript
    Promise.allSettled([promise1, promise2, promise3])
      .then((results) => {
        console.log("All Promises settled:", results);
      })
      .catch((error) => {
        console.error("One or more Promises rejected:", error);
      });
```

>  Never forget: any promise, you can use finally method which will be executed after executing promise.

### Which are the difference between them?

The key differences between these methods are in the way they handle multiple Promises, and in the values that they resolve or reject.

*Promise.all()* and *Promise.race()* are focused on resolving or rejecting with a single value, while *Promise.any()* and *Promise.allSettled()* are focused on aggregating the outcomes of multiple Promises. Additionally, *Promise.any()* and *Promise.allSettled()* return a Promise that always resolves, while *Promise.all()* and *Promise.race()* can result in a rejected Promise.

### What powerful technique when need to cancel?

Cancellation in JavaScript Promises refers to the ability to abort a Promise chain before it completes. Cancellation can be useful for optimizing performance, reducing memory usage, and improving user experience by allowing users to interrupt long-running operations.

```javascript
    const controller = new AbortController();
    const signal = controller.signal;
    
    const promise = new Promise((resolve, reject) => {
      if (signal.aborted) {
        reject(new Error("Promise cancelled"));
      } else if (error) {
        reject(error);
      } else {
        resolve(result);
      }
    });
    
    // Set a timeout to cancel the Promise after 5 seconds
    setTimeout(() => {
      controller.abort();
    }, 5000);
```

>  One powerful technique using the [AbortController API](https://developer.mozilla.org/en-US/docs/Web/API/AbortController) is in combination with the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) for making HTTP requests but don’t worry that I’ll explain it in the next article.

So, If you want to know more about async/await, please wait for the next article that I'll publish.

Thank you for reading, I hope this article can somehow have increased your knowledge base about it.