Parallel API Calls in React

Loading

In many React applications, it’s common to make multiple API requests to fetch data from different endpoints simultaneously. Rather than waiting for each request to complete one after the other, parallel API calls can improve performance by allowing multiple requests to run concurrently.

React doesn’t provide built-in mechanisms for making parallel API calls, but you can use JavaScript’s Promise.all or Promise.allSettled to handle multiple API requests in parallel.


1. Making Parallel API Calls Using Promise.all

Promise.all allows you to execute multiple promises concurrently and wait for all of them to complete. It returns a single promise that resolves when all of the input promises resolve.

Example: Parallel API Calls with Promise.all

import React, { useEffect, useState } from 'react';

// Function to fetch data
const fetchData = (url) => fetch(url).then((res) => res.json());

const App = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    // Define multiple API endpoints
    const endpoints = [
      'https://api.example.com/data1',
      'https://api.example.com/data2',
      'https://api.example.com/data3',
    ];

    // Make parallel API calls using Promise.all
    Promise.all(endpoints.map((url) => fetchData(url)))
      .then((results) => {
        // Set the fetched data
        setData(results);
        setLoading(false);
      })
      .catch((err) => {
        // Handle errors
        setError(err);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h1>API Data:</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

export default App;

Explanation:

  • In this example, Promise.all is used to run three API calls in parallel.
  • fetchData is a simple function that fetches data from a given URL.
  • Once all the data is fetched, the results are stored in the data state and displayed.

Benefits of Promise.all:

  • It runs all the promises concurrently, reducing the overall waiting time.
  • If all the promises succeed, you get the data at once.

2. Handling Errors in Parallel API Calls

When using Promise.all, if one of the API calls fails, it will reject the entire promise, and none of the results will be returned. To handle errors more gracefully and continue processing successful requests, you can use Promise.allSettled.


3. Using Promise.allSettled for Better Error Handling

Promise.allSettled waits for all promises to either resolve or reject and returns an array of results, each containing the status of the individual promise.

Example: Parallel API Calls with Promise.allSettled

import React, { useEffect, useState } from 'react';

// Function to fetch data
const fetchData = (url) => fetch(url).then((res) => res.json());

const App = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    // Define multiple API endpoints
    const endpoints = [
      'https://api.example.com/data1',
      'https://api.example.com/data2',
      'https://api.example.com/data3',
    ];

    // Make parallel API calls using Promise.allSettled
    Promise.allSettled(endpoints.map((url) => fetchData(url)))
      .then((results) => {
        const successData = results
          .filter((result) => result.status === 'fulfilled')
          .map((result) => result.value);

        const failedData = results
          .filter((result) => result.status === 'rejected')
          .map((result) => result.reason);

        // Set the fetched data
        setData(successData);
        setError(failedData.length > 0 ? failedData : null);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {JSON.stringify(error)}</div>;

  return (
    <div>
      <h1>API Data:</h1>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

export default App;

Explanation:

  • Promise.allSettled ensures that even if one of the API calls fails, the other successful responses are still processed.
  • It returns an array where each entry contains the status (either “fulfilled” or “rejected”) and the corresponding data or error for each API call.
  • The results are filtered to separate successful data and errors.

4. Using SWR or React Query for Parallel API Calls

For more advanced usage and better handling of parallel API calls with features like caching, automatic retries, and background revalidation, you might want to consider using libraries like SWR or React Query. Both libraries are built specifically for data fetching and come with built-in hooks that simplify making parallel requests.

Example: Using SWR for Parallel API Calls

import React from 'react';
import useSWR from 'swr';

// Fetch function
const fetcher = (url) => fetch(url).then((res) => res.json());

const App = () => {
  // Define multiple API endpoints
  const { data: data1, error: error1 } = useSWR('https://api.example.com/data1', fetcher);
  const { data: data2, error: error2 } = useSWR('https://api.example.com/data2', fetcher);
  const { data: data3, error: error3 } = useSWR('https://api.example.com/data3', fetcher);

  if (error1 || error2 || error3) return <div>Error loading data.</div>;
  if (!data1 || !data2 || !data3) return <div>Loading...</div>;

  return (
    <div>
      <h1>API Data:</h1>
      <pre>{JSON.stringify([data1, data2, data3], null, 2)}</pre>
    </div>
  );
};

export default App;

Explanation:

  • SWR simplifies the process by handling data fetching and caching automatically.
  • It returns a data and error object for each request, and you can check if all requests have successfully returned data before rendering.

Leave a Reply

Your email address will not be published. Required fields are marked *