如题,实现一个异步任务调度器 Scheduler,可以按需实现并发数量控制。
思路梳理
首先使用 Scheduler.addTask 持续添加异步任务。按照条件添加到对应列表,doingList 执行列表 waitingList 缓存列表。
其次每成功执行一次 doingList,需要从waitingList 获取新任务并且更新队列。这里的核心点是:异步任务完成后如何通知调度器。有两种方式可以实现:
- 第一种使用 Promise.resolve() 一路传递状态;
- 第二种异步任务完成后手动调用方法通知 Scheduler;
最后循环执行第二步,直到 doingList 为空。
Promise 方式
class Scheduler {
constructor(num) {
this.num = num;
this.doingList = [];
this.waitingList = [];
}
addTask(task) {
return new Promise((resolve, reject) => {
task.resolve = resolve;
task.reject = reject;
if (this.doingList.length < this.num) {
this.doingList.push(task);
this.performTask(task);
} else {
this.waitingList.push(task);
}
});
}
performTask(task) {
task().then(() => {
task.resolve();
}, task.reject).then(() => {
console.log('当前并行任务数', this.doingList.length);
const index = this.doingList.indexOf(task);
this.doingList.splice(index, 1);
if (this.waitingList.length) {
const nextTask = this.waitingList.shift();
this.doingList.push(nextTask);
this.performTask(nextTask);
}
});
}
}
function createAsyncTask(count) {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
console.log(`执行时间${count}s`);
}, count * 1000);
});
}
const scheduler2times = new Scheduler(2);
scheduler2times.addTask(() => createAsyncTask(2)).then(() => { console.log('任务1执行完成'); });
scheduler2times.addTask(() => createAsyncTask(3)).then(() => { console.log('任务2执行完成'); });
scheduler2times.addTask(() => createAsyncTask(1)).then(() => { console.log('任务3执行完成'); });
scheduler2times.addTask(() => createAsyncTask(1)).then(() => { console.log('任务4执行完成'); });
scheduler2times.addTask(() => createAsyncTask(1)).then(() => { console.log('任务5执行完成'); });
手动调用方式
class Scheduler {
constructor(limit) {
this.limit = limit;
this.task = [];
this.woringCount = 0;
}
preform(at) {
if (this.woringCount < this.limit) {
this.runner(at);
} else {
console.log('limit:', this.limit);
this.task.push(at);
}
}
runner(at) {
this.woringCount = this.woringCount + 1;
console.log('workgingCount:', this.woringCount);
at();
}
complate(id) {
console.log('finished:', id);
this.woringCount = this.woringCount - 1;
console.log('workgingCount:', this.woringCount);
this.nextTask();
}
nextTask() {
if (!this.task.length && this.woringCount !== 0) {
console.log('task no reat');
} else if (this.woringCount === 0) {
console.log('finish all');
} else {
this.runner(this.task.shift());
}
}
addTask(fn) {
this.task.push(fn);
}
}
const schedule = new Scheduler(2);
function asyncTask(time) {
return () => {
setTimeout(() => {
console.log(`finish async task: ${time}`);
schedule.complate(time);
}, time);
};
}
const at1 = asyncTask(2000);
const at2 = asyncTask(3000);
const at3 = asyncTask(4000);
const at4 = asyncTask(5000);
schedule.preform(at1);
schedule.preform(at2);
schedule.preform(at3);
schedule.preform(at4);
「 一枚前端学习小透明,努力学习前端知识,同时分享自己对生活的一些思考,欢迎一起讨论交流。如果我的文章对你有帮助,请点个赞,会非常感恩你的鼓励。完」
[两种实现方式异步任务调度器 | 创作者训练营 征文活动正在进行中......]