Understanding the Promise API in JavaScript

Understanding the Promise API in JavaScript

Understanding the Promise API in JavaScript

The Promise API in JavaScript provides methods to handle multiple promises concurrently. These methods—Promise.all(), Promise.allSettled(), Promise.race(), and Promise.any()—are powerful tools for managing asynchronous operations. Let’s explore each in detail.


1. Promise.all()

The Promise.all() method takes an iterable (e.g., an array) of promises and returns a single promise that:

  • Resolves when all the promises in the array have resolved.

  • Rejects if any of the promises in the array reject, returning the reason for the first rejected promise.

Use Case

Use Promise.all() when you need all promises to succeed, and their results can be used collectively.

Syntax

Promise.all([promise1, promise2, ...])
  .then(results => {
    // All promises resolved
    console.log(results);
  })
  .catch(error => {
    // At least one promise rejected
    console.error(error);
  });

Example

const promise1 = Promise.resolve(10);
const promise2 = Promise.resolve(20);
const promise3 = Promise.resolve(30);

Promise.all([promise1, promise2, promise3])
  .then(results => console.log(results)) // Output: [10, 20, 30]
  .catch(error => console.error(error));

const failingPromise = Promise.reject("Error!");

Promise.all([promise1, failingPromise])
  .then(results => console.log(results))
  .catch(error => console.error(error)); // Output: Error!

2. Promise.allSettled()

The Promise.allSettled() method takes an iterable of promises and returns a single promise that:

  • Resolves when all promises settle (i.e., resolve or reject).

  • Provides an array of objects, each describing the outcome of each promise (status and value or reason).

Use Case

Use Promise.allSettled() when you need to know the outcome of all promises, regardless of whether they resolve or reject.

Syntax

Promise.allSettled([promise1, promise2, ...])
  .then(results => {
    console.log(results);
  });

Example

const promise1 = Promise.resolve(10);
const promise2 = Promise.reject("Error!");
const promise3 = Promise.resolve(30);

Promise.allSettled([promise1, promise2, promise3])
  .then(results => console.log(results));
/*
Output:
[
  { status: 'fulfilled', value: 10 },
  { status: 'rejected', reason: 'Error!' },
  { status: 'fulfilled', value: 30 }
]
*/

3. Promise.race()

The Promise.race() method takes an iterable of promises and returns a single promise that:

  • Settles (resolves or rejects) as soon as the first promise settles (whichever happens first).

Use Case

Use Promise.race() when you are interested in the fastest promise, regardless of whether it resolves or rejects.

Syntax

Promise.race([promise1, promise2, ...])
  .then(result => {
    // First promise to settle
    console.log(result);
  })
  .catch(error => {
    console.error(error);
  });

Example

const promise1 = new Promise(resolve => setTimeout(() => resolve("First!"), 100));
const promise2 = new Promise(resolve => setTimeout(() => resolve("Second!"), 200));

Promise.race([promise1, promise2])
  .then(result => console.log(result)) // Output: "First!"
  .catch(error => console.error(error));

const failingPromise = new Promise((_, reject) => setTimeout(() => reject("Error!"), 50));

Promise.race([failingPromise, promise1])
  .then(result => console.log(result))
  .catch(error => console.error(error)); // Output: "Error!"

4. Promise.any()

The Promise.any() method takes an iterable of promises and returns a single promise that:

  • Resolves as soon as the first promise resolves.

  • Rejects only if all promises reject, with an AggregateError containing the rejection reasons.

Use Case

Use Promise.any() when you need the first successful result and can ignore failures.

Syntax

Promise.any([promise1, promise2, ...])
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.error(error);
  });

Example

const promise1 = Promise.reject("Error 1");
const promise2 = Promise.reject("Error 2");
const promise3 = Promise.resolve(30);

Promise.any([promise1, promise2, promise3])
  .then(result => console.log(result)) // Output: 30
  .catch(error => console.error(error));

const allFailing = [Promise.reject("Error A"), Promise.reject("Error B")];

Promise.any(allFailing)
  .then(result => console.log(result))
  .catch(error => console.error(error)); 
/*
Output: AggregateError: All promises were rejected
*/

Comparison of Promise Methods

MethodWhen Does It Resolve?When Does It Reject?Use Case
Promise.all()When all promises resolveIf any promise rejectsWait for all promises to resolve successfully
Promise.allSettled()When all promises settleNeverGet the outcome (fulfilled/rejected) of all promises
Promise.race()As soon as the first promise settlesIf the first settled promise rejectsUse the result of the first promise to settle, regardless of resolution or rejection
Promise.any()As soon as the first promise resolvesIf all promises rejectReturn the first successful result; ignore rejections

Conclusion

Understanding the Promise API is crucial for handling asynchronous operations in JavaScript effectively. Each method serves a specific purpose:

  • Use Promise.all() for aggregating results when all promises succeed.

  • Use Promise.allSettled() for handling both successes and failures collectively.

  • Use Promise.race() to act on the fastest promise.

  • Use Promise.any() to retrieve the first successful promise while ignoring rejections.

Master these methods, and you’ll be well-equipped to manage complex async tasks in your projects! 🚀