Ejiro Asiuwhu Frontend engineer with rock-solid experience in building complex interactive applications with JavaScript, TypeScript, Vue.js, NuxtJS, React, Next.js, and other tools in the JS ecosystem. I regularly author meaningful technical content ✍🏽.

Using axios.all to make concurrent requests

5 min read 1543

Using Axios.all To Make Concurrent Requests

axios.all is a helper method built into Axios to deal with concurrent requests. Instead of making multiple HTTP requests individually, the axios.all method allows us to make multiple HTTP requests to our endpoints altogether.

The axios.all function accepts an iterable object that must be a promise, such as a JavaScript array, and it returns an array of responses.

In this post, we’ll learn how to use the axios.all function to make HTTP requests, the difference between using Promise.all and axios.all, and making concurrent API requests in Axios.

Using axios.all

To begin using the axios.all method, let’s make an HTTP request to the following endpoints:

let endpoints = [
  'https://api.github.com/users/ejirocodes',
  'https://api.github.com/users/ejirocodes/repos',
  'https://api.github.com/users/ejirocodes/followers',
  'https://api.github.com/users/ejirocodes/following'
];

axios.all(endpoints.map((endpoint) => axios.get(endpoint))).then(
  (data) => console.log(data),
);

Here, we declare an array of endpoints we call endpoints and call the .all method on our Axios instance. This maps through each of the items in the endpoints’ array. Then, using the GET method on the Axios instance to make a request to our list of endpoints, we get each response from the server.

This request returns an array as a response and the data in the array is ordered according to our endpoints array, meaning Axios must first get data from the following endpoint:

https://api.github.com/users/ejirocodes

Then, the last data returned from the endpoint is the following:

https://api.github.com/users/ejirocodes/following

Now, let’s open the browser developer console and network tabs to confirm the order of the API response.

console tab

network tab

We made a custom demo for .
No really. Click here to check it out.

You may be thinking of sticking to making multiple API requests separately using the regular GET method. But, unlike the axis.get method where, if one promise resolves or rejects, it doesn’t affect the others. With the axios.all method, if one of our promises fails, the entire request fails.

This implies that for us to get a successful response from our endpoints when using axios.all, all the requests must be successful.

Now let’s refactor our code by adding the axios.spead method. This method accepts a callback and can destructure our array of responses, which makes our code more readable:

let endpoints = [
  'https://api.github.com/users/ejirocodes',
  'https://api.github.com/users/ejirocodes/repos',
  'https://api.github.com/users/ejirocodes/followers',
  'https://api.github.com/users/ejirocodes/following'
];

axios.all(promises.map((promise) => axios.get(promise))).then(
  axios.spread((user, repos, followers, following) => {
    console.log({ user, repos, followers, following });
  })
);

Notice how helpful the axios.spread helper function is: we can use it to get all the data at once and then use it in the callback.

By calling axios.spread((user, repos, followers, following) like this, we can say we want to name the first response from our Axios calls, user and repo.

Now, let’s take what we have at the top a little bit further; let’s pull out the data object that will be sent by the server:

axios.all(endpoints.map((endpoint) => axios.get(endpoint))).then(
  axios.spread(({data: user}, {data:repos}, {data:followers}, {data:following}) => {
    console.log({ user, repos, followers, following });
  })
);

We can do this with Axios’ response schema for every request that contains the following data object, which is the response provided by the server.

So essentially, we use object destructuring to unpack values, that is, unpacking data from the response objects into distinct variables, like user, repos, followers, and following.

Also, notice that we are destructuring data from each response and renaming it user, repos, followers, and following, respectively.

Promise.all vs. axios.all

As of July 15, 2020, Axios updated its GitHub README file to reflect that the axios.all helper method has been deprecated and should be replaced with Promise.all.

Since there is an unofficial proposal to get rid of both the axios.all and axios.spread methods completely in version 1 of Axios, let’s see how we can deprecate the axios.all methods using native JavaScript features like Promise.all and ES6 parameter destructuring.

Note that only the docs provide this depreciation, not the codebase/library. So, axios.all still works in the latest version of Axios, and many developers still use axios.all in modern codebase. Pointing out the deprecation is in anticipation that axios.all could be replaced at some point in the future.

There is one important thing we should consider at this point, however. The axios.all is a helper method built with the native Promise.all method in JavaScript. This implies we can easily replace the axios.all method with promise.all.

The Promise.all method returns a promise that resolves when all of the promises in the iterable argument resolve.

Now, let’s see this in action:

let endpoints = [
  'https://api.github.com/users/ejirocodes',
  'https://api.github.com/users/ejirocodes/repos',
  'https://api.github.com/users/ejirocodes/followers',
  'https://api.github.com/users/ejirocodes/following'
];

// Return our response in the allData variable as an array
Promise.all(endpoints.map((endpoint) => axios.get(endpoint))).then(
  axios.spread((...allData) => {
    console.log({ allData });
  })
);

The code above gives us the same results as using the axios.all method.

Notice that even if we’ve gotten rid of axios.all method, we are still using the axios.spread helper; the ES6 destructuring operator can easily replace this.

Also notice that we are using both array and object destructuring in one go to pull out only the data object sent by the server:

Promise.all(endpoints.map((endpoint) => axios.get(endpoint))).then(([{data: user}, {data: repos}, {data: followers}, {data: following}] )=> {
      console.log({ user, repos, followers, following });
});

And, voila! We’ve successfully used native JavaScript methods to make a concurrent HTTP request.

Concurrent API requests in React with Promise.all and Axios

To make simultaneous API requests in a React app using Axios and Promise, we must use React Hooks.

In this example, we will get both the followers and following data of a GitHub profile. The idea is that, if for some reason, the API request for the followers data for the user’s GitHub profile is unsuccessful, we can’t get the response for the followers data for the user’s GitHub profile.

This means the request for the user’s GitHub user profile follwing count will also fail.

This is because when we make concurrent requests, the response from one request depends on the other. So, essentially, we want both or all requests to fail if at least one fails.

Github followers and following

Using Promise.all and ES6 destructuring, let’s write a function that will perform multiple GET requests concurrently in our React app:

// In our component, we have to save both data in our state using the useState hook
  const [followers, setFollowers] = useState([])
  const [followings, setFollowing] = useState([])

  const getGithubData = () => {
    let endpoints = [
      'https://api.github.com/users/ejirocodes',
      'https://api.github.com/users/ejirocodes/repos',
      'https://api.github.com/users/ejirocodes/followers',
      'https://api.github.com/users/ejirocodes/following'
    ];
    Promise.all(endpoints.map((endpoint) => axios.get(endpoint))).then(([{data: user}, {data: repos}, {data: followers}, {data: followings}] )=> {
      setFollowers(followers)
      setFollowing(followings)
    });
  }

Next, let’s call the function when the page loads. To achieve this the React way, we’ll use theuseEffect Hook:

// remember to import useEffect from react
  useEffect(() => {
    getGithubData();
  }, []);

Then, render both the followers and following data we just received from the various endpoints to the DOM:

// Wherever your return statement is in your React app
      <section style={{ display: 'flex' }}>
          <section>
            <h2>Followers</h2>
            {followers.length > 0 && (
              <div>
                {followers.map((follower) => (
                  <div key={follower.id}>
                    <img src={follower.avatar_url} alt={follower.html_url} />
                    <p>GitHub Profile: {follower.html_url}</p>
                  </div>
                ))}
              </div>
            )}
          </section>
          <section>
            <h2>Following</h2>
            {followings.length > 0 && (
              <div>
                {followings.map((following) => (
                  <div key={following.id}>
                    <img src={following.avatar_url} alt={following.html_url} />
                    <p>GitHub Profile: {following.html_url}</p>
                  </div>
                ))}
              </div>
            )}
          </section>
        </section>

Conclusion

In this post, we’ve covered how to make concurrent HTTP requests using the axios.all method, which is built on top of the Promise.all JavaScript method underneath the hood.

We also saw how to unpack our response array using the axios.spread helper function and looked at how it can be replaced with ES6 parameter destructuring, specifically, the array and object destructuring methods.

And finally, we discussed how to use Hooks in React to make concurrent API requests using Axios and the native JavaScript Promise.all method.

I created a repository on GitHub containing all the methods we’ve covered in this post if you would like to see the source code.

That’s all for now! Let me know in the comments section below what you thought of this article. I am social on Twitter and LinkedIn. Thank you for reading and stay tuned for more.

: Full visibility into your web apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

: Debug JavaScript errors more easily by understanding the context

Debugging code is always a tedious task. But the more you understand your errors the easier it is to fix them.

LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to find out exactly what the user did that led to an error.

LogRocket records console logs, page load times, stacktraces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!

.
.
Ejiro Asiuwhu Frontend engineer with rock-solid experience in building complex interactive applications with JavaScript, TypeScript, Vue.js, NuxtJS, React, Next.js, and other tools in the JS ecosystem. I regularly author meaningful technical content ✍🏽.

Leave a Reply