🐶 来来来,整一个简单的串行任务调度器(支持顺序执行及暂停任务)
前言:
在计算机系统中,任务调度是一项关键的管理任务的技术。它通过合理地安排和管理任务的执行顺序和时间,以提高系统的性能、资源利用率和响应时间。
本文将实现一个基于 JavaScript 实现的串行任务调度器,探讨其作用、原理。
附带简单的测试用例
实际效果

代码需求
实现一个任务调度器,提供串行执行任务能力
,异步任务处理
,中断任务队列执行
代码实现
class TPromise {
// 任务列表
taskList = [];
// 任务停止标识
stop = false;
// 宏观promise
macroscopicPromise = "";
// 任务添加
addTask(fn, pause = false) {
this.taskList.push({
fn,
pause,
});
}
// 宏观任务执行
macroscopicExecuteTask(d = "") {
this.macroscopicPromise = new Promise((resolve, reject) => {
this.executeTask(d, resolve, reject);
});
}
// 真实任务执行
executeTask(d = "", resolve, reject) {
if (this.taskList.length && !this.stop) {
this.resolveTask(this.taskList[0].fn, d)
.then((res) => {
if (this.taskList[0].pause) {
this.stopCh();
resolve(res);
}
this.taskList.shift();
this.executeTask(res, resolve, reject);
})
.catch(() => {
this.stopCh();
});
}
}
// 任务重启
nextTask() {
this.macroscopicPromise.then((res) => {
this.stopCh(false);
this.macroscopicExecuteTask(res);
});
}
stopCh(bool = true) {
this.stop = bool;
}
resolveTask(fn, d) {
let resP = new Promise((resolve, reject) => {
if (fn instanceof Promise) {
// 任务是否Promise,是则resolve其Promise结果
fn.then((res) => {
resolve(res);
}).then((rej) => {
reject(rej);
});
} else if (
(typeof fn === "object" || typeof fn === "function") &&
fn !== null
) {
let then = fn.then;
if (then) {
// 任务是否thenable,是则执行其then方法,函数决定是否resolve
then.call(fn, d, resolve, reject);
} else if(typeof fn === "function") {
// 是否正常函数,是则执行函数,函数决定是否resolve
fn(d, resolve, reject);
} else {
// 若fn为非thenable对象直接返回
resolve(fn)
}
} else {
// 若fn为基本数据类型或数组等直接返回
resolve(fn)
}
});
return resP;
}
}
代码解析
上述代码实现了一个名为 TPromise
的任务调度器。它采用了基于 Promise 的异步编程模型,通过添加任务到任务列表中,并按照添加顺序依次执行任务。具体的原理如下:
- 任务添加:通过
addTask
方法,可以向任务列表中添加任务。每个任务由一个函数fn
表示,可以根据需要传入参数pause
选择是否在执行该任务后暂停任务调度器。 - 宏观任务执行:通过
macroscopicExecuteTask
方法,将macroscopicPromise
赋值为一个promise,并在promise中执行executeTask
方法,即真实任务执行函数,同时传入macroscopicPromise
的resolve和reject函数,只有当任务队列中出现暂停标识的任务时才会执行resolve方法,通过这一步去实现异步任务的暂停。 - 任务执行:通过
executeTask
方法,任务调度器会按照任务列表中的顺序执行任务。如果任务列表不为空且任务调度器未被停止,则会执行任务列表中的第一个任务,当成功之后,会校验当前是否需要暂停任务,如果需要暂停则调用stopCh
更新任务调度器为停止状态,并执行macroscopicPromise
的resolve方法返回结果。 无论是否需要暂停,都会消费当前执行的任务,基于暂存的执行结果继续递归执行executeTask
同时将接收的macroscopicPromise
的resolve和reject函数作为参数继续传入。 - 任务状态更新:通过
stopCh
方法,可以控制任务调度器的停止状态。传入true
表示停止任务调度器,传入false
表示恢复任务调度器的执行。 - 任务重启执行:通过
nextTask
方法重启任务,因为宏观任务执行会将macroscopicPromise
赋值为一个promise,这个promise只有当任务暂停的时候才会resolve结果,所以在macroscopicPromise
的then操作中重新调用stopCh
方法和macroscopicExecuteTask
方法,可以将当前任务执行状态改成启动状态,并且基于暂停的任务结果,重新执行剩下的任务,直到出现另一个暂停标识为止。 - 任务解析:通过
resolveTask
方法,任务调度器会解析传入的Task。resolveTask
函数返回的是一个 Promise 对象,支持解析promise、function、thenable、对象、数组及基础数据类型
,resolve对应的执行结果
简单用例:
function text(params, res, rej) {
return new Promise(() => {
console.log("开始", params);
setTimeout(() => {
console.log("结束", params);
res(params);
}, params);
});
}
function text1(params, resolve, reject) {
console.log("测试");
resolve(5000);
}
T.addTask(text);
T.addTask(text1, true);
T.addTask(text);
T.macroscopicExecuteTask(2000);
T.nextTask();
结尾:
总的来说,这个基于JavaScript的任务调度器实现了串行执行任务、异步任务处理以及中断任务队列执行等功能。 我们也可以在此基础上进行扩展,添加更多的功能和特性,使任务调度器更加强大和实用。
转载自:https://juejin.cn/post/7261231729523146789