Vue並發隊列-最大並發數量限制


需求:

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

實現:

/* eslint-disable */
export class LimitPromise {
  constructor (max) {
    // 異步任務“並發”上限
    this._max = max
    // 當前正在執行的任務數量
    this._count = 0
    // 等待執行的任務隊列
    this._taskQueue = []
  }

  /**
     * 調用器,將異步任務函數和它的參數傳入
     * @param caller 異步任務函數,它必須是async函數或者返回Promise的函數
     * @param args 異步任務函數的參數列表
     * @returns {Promise<unknown>} 返回一個新的Promise
     */
  call (caller, ...args) {
    return new Promise((resolve, reject) => {
      const task = this._createTask(caller, args, resolve, reject)
      if (this._count >= this._max) {
        // console.log('count >= max, push a task to queue')
        this._taskQueue.push(task)
      } else {
        task()
      }
    })
  }

  /**
     * 創建一個任務
     * @param caller 實際執行的函數
     * @param args 執行函數的參數
     * @param resolve
     * @param reject
     * @returns {Function} 返回一個任務函數
     * @private
     */
  _createTask (caller, args, resolve, reject) {
    return () => {
      // 實際上是在這里調用了異步任務,並將異步任務的返回(resolve和reject)拋給了上層
      caller(...args)
        .then(resolve)
        .catch(reject)
        .finally(() => {
          // 任務隊列的消費區,利用Promise的finally方法,在異步任務結束后,取出下一個任務執行
          this._count--
          if (this._taskQueue.length) {
            // console.log('a task run over, pop a task to run')
            let task = this._taskQueue.shift()
            task()
          } else {
            // console.log('task count = ', count)
          }
        })
      this._count++
      // console.log('task run , task count = ', count)
    }
  }
}

使用:

假設我們有一個請求方法this.$http.post方法,一般情況下,是這樣使用的

function requestDemo(){
    this.$http.post('/xxx/xxx').then(({ data: res }) => {
        //處理返回結果
    }).catch((err) => {
        //處理異常情況
    })
}

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

 
// 並發隊列
import { LimitPromise } from '@/utils/limit-promise.js'
// 請求上限
const MAX = 10
// 核心控制器
const limitP = new LimitPromise(MAX)
//請求方法
function requestDemo(){
  this.$http.post('/xxx/xxx').then(({ data: res }) => {
        //處理返回結果
    }).catch((err) => {
        //處理異常情況
    })
}
//執行
function run(){
  for(let i=0;i<100;i++){
    // 上傳 
    limitP.call(this.requestDemo, params1,params2)
  }
}

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM