前言
对于请求的并发控制也是前端优化的一个重要环节,大量的请求会给后台服务器很大的压力,也会给网络带来压力,页面会出现卡顿。上代码
使用Promise.race和async await特性实现
在以上代码中,充分利用了 Promise.all
和 Promise.race
函数特点,再结合 ES7 中提供的 async await
特性,最终实现了并发控制的功能。
利用 await Promise.race(executing);
这行语句,我们会等待 正在执行任务列表 中较快的任务执行完成之后,才会继续执行下一次循环。
//请求
let a = () => {
return new Promise((res, rej) => {
axios({
method: "get",
url: "/request"
}).then((response) => {
res(response.data)
}).catch((err) => {
rej(err)
})
})
}
//请求的并发控制
async function asyncPool(poolLimit, requestList, iteratorFn) {
const ret = []; // 存储所有的异步任务
const executing = []; // 存储正在执行的异步任务
for (const item of requestList) {
// 调用iteratorFn函数创建异步任务,请求也是在时候发出
const p = Promise.resolve().then(() => iteratorFn(item, requestList));
ret.push(p); // 保存新的异步任务
// 当poolLimit值小于或等于总任务个数时,进行并发控制
if (poolLimit <= requestList.length) {
// 当任务完成后,从正在执行的任务数组中移除已完成的任务
const e = p.then(() => executing.splice(executing.indexOf(e), 1)).catch(() => { executing.splice(executing.indexOf(e), 1) });
// 保存正在执行的异步任务
executing.push(e);
// 当任务到达设定长度时,使用await和
if (executing.length >= poolLimit) {
// 等待较快的任务执行完成
await Promise.race(executing);
}
}
}
return Promise.all(ret);
}
// 对每一个请求进行处理
function processing(everyRequest, requestList) {
return new Promise((res, rej) => {
everyRequest().then((val) => {
console.log(val);
res(val)
}).catch((err) => {
console.log(err);
rej(err)
})
})
}
asyncPool(2, [a, a, a], processing).then((val) => {
console.log(val);
}).catch((err) => {
console.log('有失败请求', err);
})
使用Promise.race
通过内部封装的 enqueue
函数来实现核心的控制逻辑。
当 Promise.race(executing)
返回的 Promise
对象变成已完成状态时,才会调用 enqueue
函数,从 requestList
数组中获取新的待办任务。
let a = () => {
return new Promise((res, rej) => {
axios({
method: "get",
url: "/request"
}).then((response) => {
res(response.data)
}).catch((err) => {
rej(err)
})
})
}
function asyncPool(poolLimit, requestList, iteratorFn) {
let i = 0;
const ret = []; // 存储所有的异步任务
const executing = []; // 存储正在执行的异步任务
const enqueue = function () {
if (i === requestList.length) {
return Promise.resolve();
}
// 获取新的任务项
const item = requestList[i++];
// 调用iteratorFn函数创建异步任务,请求也是在时候发出
const p = Promise.resolve().then(() => iteratorFn(item, requestList));
ret.push(p);
let r = Promise.resolve();
// 当poolLimit值小于或等于总任务个数时,进行并发控制
if (poolLimit <= requestList.length) {
// 当任务完成后,从正在执行的任务数组中移除已完成的任务
const e = p.then(() => executing.splice(executing.indexOf(e), 1)).catch(() => { executing.splice(executing.indexOf(e), 1) });
// 保存正在执行的异步任务;
executing.push(e);
if (executing.length >= poolLimit) {
r = Promise.race(executing);
}
}
// 正在执行任务列表 中较快的任务执行完成之后,才会调用enqueue函数requestList数组中获取新的待办任务
return r.then(() => enqueue());
};
return enqueue().then(() => Promise.all(ret));
}
// 对每一个请求进行处理
function processing(everyRequest, requestList) {
return new Promise((res, rej) => {
everyRequest().then((val) => {
console.log(val);
res(val)
}).catch((err) => {
console.log(err);
rej(err)
})
})
}
asyncPool(2, [a, a, a], processing).then((val) => {
console.log(val);
}).catch((err) => {
console.log('有失败请求', err);
})
结语
不懂的可以去试试