一、介绍
在 HOW - 日志上报实践系列(一) 我们日志采集在设计和实现时需要避免影响到正常业务代码的执行,其中一个优化就是异步处理和并发控制。
今天我们将实现一个简单的异步任务并发管理,其功能包含:
- 定义为 AsyncWorker 类
- 接受一个 capacity 参数,表示最大并发执行数
- 支持 add 实例方法,添加异步任务。在添加进去之后即可自动执行
二、实现
let task1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('task1', new Date().toString());
resolve(1000);
}, 1000);
})
}
let task2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('task2', new Date().toString());
resolve(2000);
}, 4000);
})
}
let task3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('task3', new Date().toString());
resolve(3000);
}, 2000);
})
}
class AsyncWorker {
constructor(capacity) {
this.capacity = capacity; // 最大并发执行任务数
this.count = 0; // 当前执行的任务数
this.queue = [];
}
add(task) {
return new Promise((resolve) => {
const run = async () => {
this.count++;
const result = await task();
this.count--;
resolve(result);
// run next task
this.runNext();
}
console.log('123', task, this.count, this.capacity);
if (this.count < this.capacity) {
run();
} else {
this.queue.push(run);
}
})
}
runNext() {
if (this.queue.length > 0 && this.count < this.capacity) {
const next = this.queue.shift();
next();
}
}
}
const worker = new AsyncWorker(2);
worker.add(task1);
worker.add(task2);
worker.add(task3);
在上述实现中,先执行 task1,接着执行 task2,加入 task3 时发现有已经超过 capacity,即放入队列等待。
当 task1 执行完毕,会去队列取出等待的 task2,立即执行。因此最终结果输出为:
task1
task2
task3