axios.all 是Axios内置的一个辅助方法,用于处理并发的请求。axios.all 方法不需要单独发出多个HTTP请求,而是允许我们向我们的端点发出多个HTTP请求。
axios.all 函数接受一个可迭代的对象,这个对象必须是一个承诺,比如一个JavaScript数组,它返回一个响应数组。
在这篇文章中,我们将学习如何使用axios.all 函数来进行HTTP请求,使用Promise.all 和axios.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响应的顺序。
控制台选项卡。
网络选项卡。
你可能会想坚持使用常规的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调用的第一个响应命名为:user 和repo 。
现在,让我们把上面的东西再进一步;让我们拉出将由服务器发送的数据对象。
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用户资料后续计数的请求也会失败。
这是因为当我们进行并发请求时,一个请求的响应取决于另一个。因此,从本质上讲,如果至少有一个请求失败,我们希望两个或所有请求都失败。
使用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上创建了一个仓库,包含了我们在这篇文章中所涉及的所有方法。
这就是目前的全部内容!请在下面的评论区告诉我你对这篇文章的看法。我在Twitter和LinkedIn上有社交活动。谢谢你的阅读,并请继续关注更多内容。
The postUsing axios.all to make concurrent requestsappeared first onLogRocket Blog.