如何实现异步并发限制
之前一直没有系统的去总结异步并发限制的实现思路,今天就来做个总结吧
方法1
只有一个变量
pool:代表正在执行中的任务中的集合
function sleep(name, timeOut) {
return new Promise(resolve => {
console.log(`${name}开始了`);
setTimeout(() => {
console.log(`${name}结束了`);
resolve();
}, timeOut);
})
}
const tasks = [
() => sleep(1, 1000),
() => sleep(2, 2000),
() => sleep(3, 3000),
() => sleep(5, 6000),
() => sleep(8, 8000),
];
async function parallelLimit(tasks, limit = 2) {
// 正在执行中的任务的集合
const pool = new Set();
for (const task of tasks) {
const promise = task();
pool.add(promise);
promise.then(() => pool.delete(promise));
if (pool.size >= limit) {
await Promise.race(pool);
}
}
return Promise.all(pool);
}
parallelLimit(tasks).then(() => {
console.log('任务已全部执行');
})
注意点
- 此时的 pool 代表的是:正在执行中的任务中的集合
- 使用 Promise.race 这种方式不能保证执行顺序,若要求要按顺序执行,请看第二种方法
方法2
题目要求
要求实现 Scheduler 函数,完成异步并发限制数为2的功能,且需要保证执行顺序
const scheduler = new Scheduler(2);
const timeout = (time) =>
new Promise((resolve) => {
setTimeout(resolve, time);
});
const addTask = (time, order) => {
scheduler.add(() => timeout(time).then(() => console.log(order)))
}
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
// 500ms时,2完成,输出2
// 800ms时,3完成,输出3
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4
实现方法
function Scheduler(limit) {
// 模拟队列,保存所有任务
this.pool = [];
// 当前正在执行任务的数目
this.count = 0;
this.add = function (fn) {
this.pool.push(fn);
this.run();
}
this.run = function () {
if (this.pool.length && this.count < limit) {
const task = this.pool.shift(); // 保证执行顺序
this.count++;
task().then(() => {
this.count--;
this.run();
})
}
}
}
const scheduler = new Scheduler(2);
const timeout = (time) =>
new Promise((resolve) => {
setTimeout(resolve, time);
});
const addTask = (time, order) => {
scheduler.add(() => timeout(time).then(() => console.log(order)))
}
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
// 500ms时,2完成,输出2
// 800ms时,3完成,输出3
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4
注意点
- pool 代表保存所有任务的数组
- count 代表当前正在执行任务的数目
- 保证顺序:需要从数组中顺序取出并执行
两个方法各变量代表的含义不同,实现的思路也就不同,要好好区分两种方法的思想,不然会混淆(像我一样☁️☁️☁️)
道阻且长,面试加油,边复习边查漏补缺吧!!!
passion!!!