Promise.allSettled, Promise.all, and Promise.race with Fetch API

In the realm of asynchronous programming, JavaScript offers a powerful toolkit for managing multiple promises: Promise.allSettled, Promise.all, and Promise.race. These methods, when combined with the fetch API, enable you to efficiently handle network requests and manipulate the resulting data. Let’s explore how to use these tools effectively.

Understanding the Basics

Before diving into the specifics, let’s quickly recap what these methods do:

Fetching Multiple Resources with Promise.all

When you need to fetch multiple resources simultaneously and only proceed when all have successfully loaded, Promise.all is your go-to:

async function fetchMultipleResources() {
  const urls = [
    "https://fakestoreapi.com/products",
    "https://jsonplaceholder.typicode.com/todos/1",
  ];

  try {
    const responses = await Promise.all(urls.map((url) => fetch(url)));
    const data = await Promise.all(
      responses.map((response) => response.json()),
    );

    console.log("fetchMultipleResources", data);
  } catch (error) {
    console.error("Error fetching data:", error);
  }
}

fetchMultipleResources();

In this example, we create an array of fetch promises, then use Promise.all twice: once to wait for all fetch requests to complete and again to parse the JSON responses.

Handling Potential Failures with Promise.allSettled

If you need to know the outcome of every fetch request, regardless of success or failure, Promise.allSettled is the way to go:

async function fetchMultipleResourcesWithAllSettled() {
  const urls = [
    "https://fakestoreapi.com/products",
    "https://jsonplaceholder.typicode.com/todos/1",
  ];

  try {
    const results = await Promise.allSettled(urls.map((url) => fetch(url)));

    results.forEach(async (result) => {
      if (result.status === "fulfilled") {
        console.log(
          "fetchMultipleResourcesWithAllSettled:",
          await result.value.json(),
        );
      } else {
        console.error("Error fetching:", result.reason);
      }
    });
  } catch (error) {
    console.error("Unexpected error:", error);
  }
}

fetchMultipleResourcesWithAllSettled();

This code iterates through the results, logging successful fetches and handling errors gracefully.

Prioritizing Speed with Promise.race

When you only care about the first response, or want to implement a timeout mechanism, Promise.race is useful:

async function fetchFirstAvailableResource() {
  const urls = [
    "https://fakestoreapi.com/products",
    "https://jsonplaceholder.typicode.com/todos/1",
  ];
  const timeout = new Promise((resolve) => setTimeout(resolve, 3000));

  try {
    const response = await Promise.race([
      ...urls.map((url) => fetch(url)),
      timeout,
    ]);

    if (response !== timeout) {
      const data = await response.json();
      console.log(data);
    } else {
      console.log("Timeout reached");
    }
  } catch (error) {
    console.error("Error fetching data:", error);
  }
}

fetchFirstAvailableResource();

Here, we race between multiple fetch requests and a timeout. The first to finish wins.

Conclusion

By understanding and effectively using Promise.allSettled, Promise.all, and Promise.race in conjunction with the fetch API, you can write more robust, efficient, and flexible asynchronous code. Choose the method that best suits your specific use case to optimize your application’s performance and user experience.

Latest blog posts

Explore the world of programming and cybersecurity through our curated collection of blog posts. From cutting-edge coding trends to the latest cyber threats and defense strategies, we've got you covered.