天天看點

來來來,整一個簡單的串行任務排程器(支援順序執行及暫停任務)

前言:

在計算機系統中,任務排程是一項關鍵的管理任務的技術。它通過合理地安排和管理任務的執行順序和時間,以提高系統的性能、資源使用率和響應時間。

本文将實作一個基于 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 的異步程式設計模型,通過添加任務到任務清單中,并按照添加順序依次執行任務。具體的原理如下:

  1. 任務添加:通過 addTask 方法,可以向任務清單中添加任務。每個任務由一個函數 fn 表示,可以根據需要傳入參數pause選擇是否在執行該任務後暫停任務排程器。
  2. 宏觀任務執行:通過macroscopicExecuteTask方法,将macroscopicPromise指派為一個promise,并在promise中執行executeTask方法,即真實任務執行函數,同時傳入macroscopicPromise的resolve和reject函數,隻有當任務隊列中出現暫停辨別的任務時才會執行resolve方法,通過這一步去實作異步任務的暫停。
  3. 任務執行:通過 executeTask 方法,任務排程器會按照任務清單中的順序執行任務。如果任務清單不為空且任務排程器未被停止,則會執行任務清單中的第一個任務,當成功之後,會校驗目前是否需要暫停任務,如果需要暫停則調用stopCh更新任務排程器為停止狀态,并執行macroscopicPromise的resolve方法傳回結果。 無論是否需要暫停,都會消費目前執行的任務,基于暫存的執行結果繼續遞歸執行 executeTask同時将接收的macroscopicPromise的resolve和reject函數作為參數繼續傳入。
  4. 任務狀态更新:通過 stopCh 方法,可以控制任務排程器的停止狀态。傳入 true 表示停止任務排程器,傳入 false 表示恢複任務排程器的執行。
  5. 任務重新開機執行:通過 nextTask 方法重新開機任務,因為宏觀任務執行會将macroscopicPromise指派為一個promise,這個promise隻有當任務暫停的時候才會resolve結果,是以在macroscopicPromise的then操作中重新調用stopCh方法和macroscopicExecuteTask方法,可以将目前任務執行狀态改成啟動狀态,并且基于暫停的任務結果,重新執行剩下的任務,直到出現另一個暫停辨別為止。
  6. 任務解析:通過 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

繼續閱讀