使用axios.all来进行并发请求

7,892 阅读6分钟

axios.all 是Axios内置的一个辅助方法,用于处理并发的请求。axios.all 方法不需要单独发出多个HTTP请求,而是允许我们向我们的端点发出多个HTTP请求。

axios.all 函数接受一个可迭代的对象,这个对象必须是一个承诺,比如一个JavaScript数组,它返回一个响应数组。

在这篇文章中,我们将学习如何使用axios.all 函数来进行HTTP请求,使用Promise.allaxios.all 的区别,以及在Axios中进行并发的API请求。

使用axios.all

为了开始使用axios.all 方法,让我们向以下端点发出HTTP请求

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),
);

在这里,我们声明一个名为endpoints 的端点数组,并在我们的Axios实例上调用.all 方法。这将映射出端点数组中的每个项目。然后,使用Axios实例上的GET 方法向我们的端点列表发出请求,我们从服务器上获得每个响应。

这个请求会返回一个数组作为响应,数组中的数据是根据我们的endpoints 数组排序的,这意味着Axios必须先从下面的端点获得数据。

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

然后,从端点返回的最后一个数据是以下内容。

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

现在,让我们打开浏览器开发者控制台和网络标签,确认API响应的顺序。

The Console Tab Showing The Different Arrays

控制台选项卡。

Network Tab Showing Name, Status, Type, And Initiator

网络选项卡。

你可能会想坚持使用常规的GET 方法分别提出多个API请求。但是,与axis.get 方法不同的是,如果一个承诺被解决或拒绝,它不会影响其他的。在axios.all 方法中,如果我们的一个承诺失败了,整个请求都会失败。

这意味着当我们使用axios.all ,从我们的终端获得一个成功的响应,所有的请求都必须是成功的。

现在让我们通过添加axios.spead 方法来重构我们的代码。这个方法接受一个回调,并可以对我们的响应数组进行解构,这使得我们的代码更具可读性。

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 });
  })
);

注意到axios.spread 这个辅助函数有多大的帮助:我们可以用它来一次获得所有的数据,然后在回调中使用它。

通过这样调用axios.spread((user, repos, followers, following) ,我们可以说我们想把Axios调用的第一个响应命名为:userrepo

现在,让我们把上面的东西再进一步;让我们拉出将由服务器发送的数据对象

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 });
  })
);

我们可以用Axios的响应模式来做这件事,每个请求都包含以下数据对象,这就是服务器提供的响应。

因此,从本质上讲,我们使用对象解构来解压值,即把data 从响应对象中解压成不同的变量,如user,repos,followers, 和following

另外,注意到我们正在对每个响应的数据进行解构,并分别重命名为user,repos,followers, 和following

Promise.all 与。axios.all

截至2020年7月15日,Axios更新了其GitHub的README文件,以反映axios.all 帮助方法已被废弃,应替换为 [Promise.all](https://blog.logrocket.com/understanding-promise-all-in-javascript/).

由于有一个非官方的建议,即 取消了 [axios.all](https://github.com/axios/axios/issues/1042) [axios.spread](https://github.com/axios/axios/issues/1042) 方法,让我们看看如何使用本地JavaScript特性(如Promise.all 和ES6参数重构)来废除axios.all 方法。

注意,只有文档提供了这种折旧,而不是代码库/库。所以,axios.all 在最新版本的Axios中仍然有效,许多开发者在现代代码库中仍然使用axios.all 。指出折旧是为了预期axios.all 可能在未来的某个时候被取代。

然而,在这一点上,我们应该考虑一件重要的事情。axios.all 是一个辅助方法,是用本地的 [Promise.all](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) 方法构建的辅助方法。这意味着我们可以很容易地用promise.all 替换axios.all 方法。

Promise.all 方法返回一个承诺,当迭代参数中的所有承诺都解决时,该承诺就会解决。

现在,让我们看看这个方法的操作。

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 });
  })
);

上面的代码给了我们与使用axios.all 方法相同的结果。

请注意,即使我们已经摆脱了axios.all 方法,我们仍然在使用axios.spread 帮助器;ES6 的析构操作符可以很容易地取代它。

还注意到我们同时使用了数组和对象的析构,只拉出了服务器发送的数据对象。

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

然后,瞧!我们已经成功地使用了本地JavaScript方法来进行并发的HTTP请求。

使用Promise.all 和Axios在React中并发API请求

要在React应用中使用Axios和Promise ,同时进行API请求,我们必须使用React Hooks。

在这个例子中,我们将同时获得GitHub个人资料的关注者和粉丝数据。我们的想法是,如果由于某种原因,对用户的GitHub档案的followers 数据的API请求不成功,我们就不能得到对用户的GitHub档案的followers 数据的响应。

这意味着对用户的GitHub用户资料后续计数的请求也会失败。

这是因为当我们进行并发请求时,一个请求的响应取决于另一个。因此,从本质上讲,如果至少有一个请求失败,我们希望两个或所有请求都失败。

Making Concurrent Requests With React Axios.all For GitHub Users and Follower Information

使用Promise.all 和ES6结构化,让我们写一个函数,在我们的React应用程序中并发执行多个GET 请求。

// 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)
    });
  }

接下来,让我们在页面加载时调用这个函数。为了以React的方式实现这一点,我们将使用useEffect Hook。

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

然后,将我们刚刚从各个端点收到的追随者和跟随者的数据都渲染到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>

结语

在这篇文章中,我们已经介绍了如何使用axios.all 方法进行并发的HTTP请求,该方法是建立在引擎盖下的Promise.all JavaScript方法之上的。

我们还看到了如何使用axios.spread 辅助函数来解压我们的响应数组,并研究了如何用ES6参数析构来代替它,特别是数组和对象析构方法。

最后,我们讨论了如何在React中使用Hooks来使用Axios和本地JavaScriptPromise.all 方法进行并发的API请求。

如果你想看源代码,我在GitHub上创建了一个仓库,包含了我们在这篇文章中所涉及的所有方法

这就是目前的全部内容!请在下面的评论区告诉我你对这篇文章的看法。我在TwitterLinkedIn上有社交活动。谢谢你的阅读,并请继续关注更多内容。

The postUsing axios.all to make concurrent requestsappeared first onLogRocket Blog.