使用 Promise 實現任務隊列發送請求,實現最大請求數目限制

核心

  • 設置最大請求數量,當前請求數量,待執行隊列
  • 調用時,創建一個新任務,然後判斷是否達到最大請求數量,若達到則將任務追加到待執行隊列,否則,則直接執行該任務。並返回Promise
  • 創建任務時,需要返回一個函數,當該任務開始執行則當前數量加一。當任務執行完畢時使用finally,當前數量減一,並從待執行隊列中取出新任務執行

實現

class limitPromise{
    constructor(max){
    this.max = max;
    this._count = 0;
    this._pendingTaskQueue = [];
  }
   /**
   * 調用器,將異步任務函數和它的參數傳入
   * @param caller 異步任務函數,返回Promise的函數
   * @param args 異步任務函數的參數列表
   * @returns {Promise<unknown>} 返回一個新的Promise
   */
  call = (caller, ...arg) => {
    return new Promise((resolve, reject) => {
        let task = this._createTask(caller, arg, resolve, reject);
        if(this._count >= this.max) {
        this._pendingTaskQueue.push();
        }else{
        task();
        }
    });
    }

   /**
   * 創建一個任務
   * @param caller 實際執行的函數
   * @param args 執行函數的參數
   * @param resolve
   * @param reject
   * @returns {Function} 返回一個任務函數
   * @private
   */
     _createTask = (caller, arg, resolve, reject)=> {
     return () => {
       // 當前請求數量加一
       this._count++;
       // 實際上是在這裏調用了異步任務,並將異步任務的返回(resolve和reject)拋給了上層
       caller(...arg)
         .then(resolve)
         .catch(reject)
         .finally(() => {
                // 任務隊列的消費區,利用Promise的finally方法,在異步任務結束後,取出下一個任務執行
                this._count--;
                if(this._pendingTaskQueue.length){
                let task = this._pendingTaskQueue.shift();
                task();
                } 
        })
     }
   }
}

使用

假設我們有一個網絡請求模塊,叫request.js,包含get和post方法,一般情況下,是這樣使用的

const request = require('./request')
request.get('https://www.baidu.com')
  .then((res) => {
    // 處理返回結果
  })
  .catch(err => {
    // 處理異常情況
  })

現在我們要把它改造成受限制的網絡請求,假設請求上限設爲10個,並起名叫limitRequest.js。實現如下:

const LimitPromise = require('limit-promise')
const request = require('./request')
// 請求上限
const MAX = 10
// 核心控制器
const limitP = new LimitPromise(MAX)

// 利用核心控制器包裝request中的函數
function get (url, params) {
  return limitP.call(request.get, url, params)
}
function post (url, params) {
  return limitP.call(request.post, url, params)
}
// 導出
module.exports = {get, post}

這裏就完成受限請求模塊的構建了,是不是很簡單,而且調用接口完全沒變,只需要引入limitRequest.js替代原先的即可。

參考自

https://www.jianshu.com/p/cc706239c7ef

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章