并发的定义&为什么需要控制并发
并发在前端一般是指多个请求一起发送,这样可能就会造成后端压力过大。所以我们才需要控制并发数量。
控制并发的思路
比如现在有10条请求,我们限制最大的并发数为3,那么思路就为: 1. 先定好3个位置。 2. 执行3条请求。 3. 看那一条执行完毕了,再把没有执行的请求push进去执行。 4. 一直重复步骤3直到所有请求执行完成。
具体实现代码
// iLimt: 并发的数量
function limitFn(iLimt) {
const queue = []; // 队列
let iActive = 0; // 正在执行的请求数量
const next = () => {
iActive = iActive - 1;
if (queue.length) {
queue.shift()();
}
};
const run = async (fn, resolve, ...args) => {
iActive = iActive + 1;
const result = await fn(...args);
resolve(result);
next();
};
const enqueue = (fn, resolve, ...args) => {
queue.push(run.bind(null, fn, resolve, ...args)); // bind函数会返回一个新的函数
// 如果 小于最大并发数 && 还有请求没执行完
if (iActive < iLimt && queue.length) {
queue.shift()(); // 请求出队并执行
}
};
const generator = (fn, ...args) => {
return new Promise((resolve) => {
enqueue(fn, resolve, ...args);
});
};
// 暴露内部属性给外界
Object.defineProperties(generator, {
iActive: {
get: () => iActive,
},
pendingCount: {
get: () => queue.length,
},
clearQueue: {
value: () => {
queue.length = 0;
},
},
});
return generator;
}
// 最大并发数 2
const generator = limitFn(2);
const fetchFn = (delay, index) => {
return new Promise((resolve) => {
console.log(index);
setTimeout(() => {
resolve(index);
}, delay);
});
};
const promises = [
generator(() => fetchFn(1000, 1)),
generator(() => fetchFn(1000, 2)),
generator(() => fetchFn(1000, 3)),
generator(() => fetchFn(1000, 4)),
generator(() => fetchFn(1000, 5)),
generator(() => fetchFn(1000, 6)),
];
Promise.all(promises);