JavaScript Promise.any() method (basic and advanced examples)

Updated: February 19, 2024 By: Guest Contributor Post a comment

Overview

In the realm of asynchronous operations in JavaScript, Promise.any() is a relatively new addition that provides a means of handling multiple promises. This method takes an iterable of Promise objects, and as soon as one of the promises fulfills, it returns a single promise that is fulfilled with the value of the first fulfilling promise in the iterable. If all of the passed-in promises are rejected, then the returned promise is rejected with an AggregateError, a new error type that groups together individual promise errors. In this article, we will explore basic and advanced examples of using the Promise.any() method to handle asynchronous tasks efficiently.

Understanding Promise.any()

Before diving into examples, it’s important to grasp the basics of Promise.any(). Unlike Promise.all() which waits for all promises to succeed or one to fail, Promise.any() is essentially a race to see which promise succeeds first, ignoring all rejections unless every promise fails. It’s crucial for scenarios where the resolution of just one promise is sufficient to proceed.

Basic Example

Let’s start with a simple example to understand how Promise.any() works:

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(resolve, 100, 'foo'));
const promise3 = Promise.reject(new Error('promise3 failed'));
Promise.any([promise1, promise2, promise3])
  .then(value => {
    console.log(value); // Expected output: 3
  })
  .catch(error => {
    console.error(error);
  });

In this example, promise1 resolves immediately, promise2 resolves after 100 milliseconds, and promise3 is rejected right away. Here, Promise.any() will resolve with the value of promise1, as it’s the first to fulfill among the supplied promises.

Handling Errors

What happens if all promises reject? Let’s look at this situation:

const failingPromises = [
  Promise.reject(new Error('First fails')),
  Promise.reject(new Error('Second fails')),
  Promise.reject(new Error('Third fails'))
];

Promise.any(failingPromises)
  .catch(error => {
    console.error(error);
    // This will log an AggregateError to the console
  });

Here, since all promises in the iterable are rejected, Promise.any() will throw an AggregateError containing all the rejection reasons. This demonstrates the importance of having a catch block to handle potential errors when working with Promise.any().

Advanced Examples

Now that we’ve covered the basics, let’s delve into some more complex scenarios where Promise.any() can be particularly useful.

Loading Fallback Content

In web development, you might want to load primary content but have a fallback in case the primary loading fails. Promise.any() is perfect for this scenario since it can attempt to load the primary content and fallback content simultaneously, using the result of whichever resolves first.

const primaryContent = fetch('...').then(response => response.json());
const fallbackContent = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Fallback content loaded');
  }, 200);
});

Promise.any([primaryContent, fallbackContent])
  .then(content => {
    console.log(content);
  })
  .catch(error => {
    console.error(error);
  });

This demonstrates how Promise.any() can serve as an efficient way to manage fallbacks in asynchronous operations.

Aggregate Multiple API Calls

Another advanced use case for Promise.any() is aggregating results from multiple API calls where the first successful response is sufficient. This is particularly useful in scenarios where identical data can be obtained from multiple sources.

const apiCall1 = fetch('https://example-api1.com/data');
const apiCall2 = fetch('https://example-api2.com/data');
const apiCall3 = fetch('https://example-api3.com/data');

Promise.any([apiCall1, apiCall2, apiCall3])
  .then(response => response.json())
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });

This pattern is not only elegant but also minimizes latency by not depending on the sequential completion of each API call.

Conclusion

The Promise.any() method opens up a realm of possibilities for handling asynchronous operations in JavaScript. By providing a way to act on the first resolved promise out of an array of potentially failing promises, it allows developers to write more robust, efficient, and faster-reacting code. Whether you’re handling common use cases or dealing with complex asynchronous patterns, understanding and utilizing Promise.any() can significantly improve your JavaScript coding strategies.