Appearance
前端并发请求的逻辑
指定一个url的数组,和一个最大的并发数,假定最大数是3,那么同时可发出的请求就是 3 个,当这个 3 个之中有一个完成了,就立刻取数组中的下一个url进行请求。
并且最后的返回结果的顺序,也要和url数组的顺序保持一致。

实现
根据要求,我们要封装的函数肯定是一个异步函数,返回的结果是一个Promise,而这个Promise,一定也要是完成状态的,也就是只调用resolve函数。也就是说,当A接口请求成功后,我们把成功的结果放到返回数组对应位置,如果失败了,也要把失败的信息放到返回数组的对应位置。
js
function concurRequest(urls, maxNum = 5) {
return new Promise((resolve) => {
if (urls.length === 0) {
resolve([]);
return;
}
const results = [];
let index = 0; // 下一个请求的下标
let count = 0; // 当前请求完成的数量
// 执行请求
async function request() {
if (index >= urls.length) return;
const i = index; // 保存当前下标,请求完成时把结果放到对应的位置
const url = urls[index++];
try {
const resp = await fetch(url);
// resp 加入到 results
results[i] = resp;
} catch (err) {
// err 加入到 results
results[i] = err;
} finally {
// 判断是否所有的请求都已完成
if (++count >= urls.length) {
resolve(results);
}
// 当前请求完成后,继续取下一个 url 执行请求
request();
}
}
// 防止最大请求数超出了实际的 url 个数
const times = Math.min(maxNum, urls.length);
// 发出并发请求
for (let i = 0; i < times; i++) {
request();
}
});
}使用
js
const urls = [];
for (let i = 1; i <= 10; i++) {
urls.push(`https://jsonplaceholder.typicode.com/todos/${i}`);
}
// 最大并发数 3
concurRequest(urls, 3).then((resps) => {
console.log(resps);
});