// 并发请求函数,最多maxNum并行请求
const concurrencyRequest = (urls, maxNum) => {
return new Promise((resolve) => {
if (urls.length === 0) {
resolve([]);
return;
}
const results = [];
let index = 0; // 下一个请求的下标
let count = 0; // 当前请求完成的数量
// maxNum和urls.length取最小进行调用
const times = Math.min(maxNum, urls.length);
for(let i = 0; i < times; i++) {
request();
}
// 发送请求
async function request() {
if (index === urls.length) return;
const i = index; // 保存序号,使result和urls相对应
const url = urls[index];
index++;
console.log(url);
try {
// 阻塞后面代码 会在这等待resp
const resp = await fetch(url);
// resp 加入到results
results[i] = resp;
} catch (err) {
// err 加入到results
results[i] = err;
} finally {
// 请求完成
count++;
// 判断是否所有的请求都已完成
if (count === urls.length) {
console.log('完成了');
resolve(results);
}else{
request();
}
}
}
})
}
await concurrencyRequest()
// 解法2
// // 最大允许三个请求并发,有一个返回后可以请求下一个
const request = createRequest(3);
// 假设调了五个 只有三个可以一开始并发进行
for (var i = 0; i < 5; i++) {
request('/api').then((d) => console.log(d))
}
// ======>
// ====>
// ========>
// =====>
// ======>
//
function createRequest(count) {
let num = 0
let requestPromise = []
return async function request(url) {
// 如果当前的调用数 小于count 那么直接调用
num++
if(num < count) {
return startRequest()
}else{
await Promise.race([requestPromise])
return startRequest()
}
function startRequest(){
let curPromise = new Promise((resolve, reject) => {
fetch(url).then(()=>{
resolve("success")
num--
},()=>{
reject("failed")
num--
})
})
// 最关键的一步 利用链式回调消除自己
const e = curPromise.then(()=>{
requestPromise.splice(requestPromise.indexOf(e),1)
},()=>{
requestPromise.splice(requestPromise.indexOf(e),1)
})
requestPromise.push(e)
return curPromise
}
}
}
console