场景:比如前端轮询上传多张图片(几十几百张),控制并发上传数量
1.发送全部请求,即便中间有进入reject的
// 模拟ajax请求
const getRequest = (n) => {
return new Promise((resolve, reject) => {
// 请求0-3s返回
const t = Math.random() * 3 * 1000
setTimeout(() => {
console.log(`${n}完成,耗时${t}`);
resolve([n, t])
}, t)
})
}
// 主函数
const limitRequest = async(maxRequstQuantity, allReq, fetchFn) => {
const result = [];
const queue = [];
for (let i = 0; i < allReq; i++) {
console.log(`${i}发起请求`);
const promise = fetchFn(i);
// 执行完从queue中删除自身
promise.finally(() => {
const index = queue.indexOf(promise); // queue.indexOf(promise)是可以找到正确位置的
console.log(`${i}完成,当前所在位置`, index);
queue.splice(index, 1);
})
result.push(promise);
queue.push(promise);
// 如果queue中的数量达到maxRequstQuantity,等一个请求完成再进行后面的for循环(这里是关键,阻塞for)
if (queue.length >= maxRequstQuantity) {
await Promise.race(queue);
}
}
return Promise.allSettled(result); // Promise.allSettled所有请求执行完,不区分状态是res还是rej([{"status": "fulfilled","value": [0,118]}])
}
2.当有请求失败时,结束后面的请求(场景:前端弹框提示错误)
// 模拟ajax请求,n为4的请求进入reject
const getRequest = (n) => {
return new Promise((resolve, reject) => {
// 请求0-3s返回
const t = Math.random() * 3 * 1000
setTimeout(() => {
console.log(`${n}完成,耗时${t}`);
if (n != 4) {
resolve([n, t])
} else {
reject([n, t])
}
}, t)
})
}
// 主函数
const limitRequest2 = async(maxRequstQuantity, allReq, fetchFn) => {
const result = [];
const queue = [];
try {
for (let i = 0; i < allReq; i++) {
console.log(`${i}发起请求`);
const promise = fetchFn(i);
// 执行完且成功,从queue中删除自身
promise.then(() => {
const index = queue.indexOf(promise); // queue.indexOf(promise)是可以找到正确位置的
// console.log(`${i}完成,当前所在位置`, index);
queue.splice(index, 1);
})
result.push(promise);
queue.push(promise);
// 如果queue中的数量达到maxRequstQuantity,等一个请求完成再进行后面的for循环(这里是关键,阻塞for)
if (queue.length >= maxRequstQuantity) {
await Promise.race(queue)
}
}
} catch(err) {
// 可以拿到错误的请求是哪个
console.log('err', err)
}
return Promise.allSettled(result) // Promise.allSettled所有请求执行完,不区分状态是res还是rej([{"status": "fulfilled","value": [0,118]}])
}
测试函数,执行limitRequest为例(发送全部请求)
const test = async() => {
// results的数据结构是[{"status": "fulfilled","value": [0,118]}],自己判断每个请求的状态
const results = await limitRequest(3, 8, getRequest);
console.log(results)
const results2 = await limitRequest(3, 10, getRequest);
console.log(results2);
}
test()执行输出
(1)await limitRequest(3, 8, getRequest);
(2)await limitRequest(3, 10, getRequest);