切換語言為:簡體

JavaScript中實現併發任務控制器

  • 爱糖宝
  • 2024-09-10
  • 2054
  • 0
  • 0

1. 引言

併發任務執行是多執行緒程式設計中的一個重要主題,當應用程式需要同時處理多個任務時,如果不加以控制,可能會導致資源過度消耗或系統負載過高。通俗的講,就是前端有一萬個請求,後端一次只能處理五十個,那麼要如何控制併發確保系統穩定執行呢?對於前端開發來說,js是單執行緒機制已經是一個偽命題了,我們透過非同步操作,可以合理地限制併發任務的數量,確保系統穩定執行,同時提高資源利用率。 下面是設計思路以及具體實現:

2. 設計併發任務控制器

我們的目標是建立一個類 SuperTask,它可以接受任務並將它們按照指定的併發數量進行排程執行。每個任務都是一個返回 Promise 的函式,這樣我們可以輕鬆地處理非同步操作。

2.1 建構函式

類中新增建構函式,初始化 SuperTask 物件的屬性:

  • parallelCount:使用者可以透過傳入引數來設定最大併發數量。預設值為2,用於接下來的測試。

  • tasks:一個數組,用於儲存等待執行的任務物件。

  • runningCount:一個計數器,記錄當前正在執行的任務數量。

class SuperTask {
  constructor(parallelCount = 2) {
    this.parallelCount = parallelCount; // 併發量
    this.tasks = [];                    // 待執行的任務佇列
    this.runningCount = 0;              // 正在執行的任務數量
  }
}

2.2 add 方法

類中新增add 方法,接收一個任務(即返回 Promise 的函式),將其封裝成一個任務物件,並新增到任務佇列中。之後呼叫 _run 方法嘗試執行佇列中的任務。

  // 新增任務到佇列
  add(task) {
    return new Promise((resolve, reject) => {
      this.tasks.push({
        task,
        resolve,
        reject
      });

      this._run();
    });
  }

2.3 _run 方法

類中新增_run 方法,這是一個私有方法,用於檢查是否有可用的併發槽位,並執行佇列中的任務。它的工作流程如下:

  1. 檢查當前正在執行的任務數量是否小於最大併發數量。

  2. 如果小於最大併發數量,並且任務佇列中有任務,則從佇列中取出一個任務並執行。

  3. 執行任務後,無論結果如何(成功或失敗),都會呼叫 .finally() 回撥來減少正在執行的任務數量,並再次呼叫 _run 方法嘗試執行佇列中的下一個任務。

  // 執行任務佇列中的任務
_run() {
    while (this.runningCount < this.parallelCount && this.tasks.length > 0) {
      const { task, resolve, reject } = this.tasks.shift();
      this.runningCount++;
      task().then(resolve, reject).finally(() => {
        this.runningCount--;
        this._run();
      });
    }
  }

2.4 使用示例

假設我們有一個簡單的延時函式 timeout,用於模擬非同步操作。

function timeout(time) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, time);
  });
}

接下來,我們可以建立一個 SuperTask 例項,並新增一些任務:

const superTask = new SuperTask(); 

function addTask(time, name) {
  superTask.add(() => timeout(time)).then(() => {
    console.log(`任務${name}完成`);
  });
}

addTask(10000, '1');
addTask(2000, '2');
addTask(5000, '3');
addTask(1000, '4');
addTask(7000, '5');
addTask(3000, '6');

總結

併發任務控制器 SuperTask,透過限制併發任務的數量來確保系統的穩定性和效率。該控制器透過維護一個任務佇列和一個執行計數器,確保在不超過設定的最大併發數量的前提下,有序地執行任務,從而實現高效的併發控制。併發任務控制器的核心在於_run()的設計,即把任務都裝在任務佇列裡,只取併發量的任務,某任務結束之後,透過遞迴再從佇列裡取任務,希望友友們在面試中遇到這類問題可以有一定的思路。

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.