并发限制器
给异步函数新增一个包装,通过传参使得并发个数受到限制
代码实现:
function withLimit(fn, num) {
let index = 0;
let queue = [];
const addTask = () => {
if (queue.length > 0) {
const task = queue.shift();
index++;
task.fn().then(res => {
task.resolve(res);
index--;
// 按照下面注释写的话会在此处循环调用有问题,主要是promise返回不出去
addTask();
}).catch(e => {
const reject = task.reject;
reject(e);
index--;
addTask();
});
}
}
return (...args) => new Promise((resolve, reject) => {
// 以下缓存会有问题
// fn.resolve = resolve;
// fn.reject = reject;
// queue.push(fn);
queue.push({
fn: () => fn.apply(this, args),
resolve,
reject
});
if (index < num) {
addTask();
}
})
}
// test
const aFn = (num1, num2) => new Promise(resolve => {
const time = Math.random() * 5000;
console.log('action', num1, num2);
setTimeout(() => {
resolve(time);
}, time);
});
const limitFn = withLimit(aFn, 5);
limitFn(4, 1).then((res) => console.log('1', res));
limitFn(4, 2).then((res) => console.log('2', res));
limitFn().then((res) => console.log('3', res));
limitFn().then((res) => console.log('4', res));
limitFn().then((res) => console.log('5', res));
limitFn().then((res) => console.log('11', res));
limitFn().then((res) => console.log('12', res));
limitFn().then((res) => console.log('13', res));
limitFn().then((res) => console.log('14', res));
limitFn().then((res) => console.log('15', res));
limitFn().then((res) => console.log('16', res));
limitFn().then((res) => console.log('17', res));
limitFn().then((res) => console.log('18', res));
limitFn(4, 19).then((res) => console.log('19', res));
返回信息:
action 4 1
action 4 2
action undefined undefined
action undefined undefined
action undefined undefined
action undefined undefined
2 3406.5749616513685
action undefined undefined
5 3457.047324525271
action undefined undefined
11 50.46502618895943
action undefined undefined
3 3570.9279378095716
action undefined undefined
4 4689.976518548516
action undefined undefined
1 4811.05540099109
action undefined undefined
14 2174.7416962970456
action undefined undefined
16 1000.5974643349125
action 4 19
12 3432.270354082213
13 4349.003107100447
15 3260.5231344090435
18 3487.247956538897
17 3614.8114057058724
19 3837.367184179581
拓展:
遗留问题:
目前队列里存储的是重建的一个对象,但是当我直接对fn赋值resolve,reject时,aFn循环调用时,无法找到原先的promise,具体参照注释里面