前言:
在計算機系統中,任務排程是一項關鍵的管理任務的技術。它通過合理地安排和管理任務的執行順序和時間,以提高系統的性能、資源使用率和響應時間。
本文将實作一個基于 JavaScript 實作的串行任務排程器,探讨其作用、原理。
附帶簡單的測試用例
實際效果
代碼需求
實作一個任務排程器,提供串行執行任務能力,異步任務處理,中斷任務隊列執行
代碼實作
js複制代碼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對應的執行結果
簡單用例:
js複制代碼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