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

原文地址:https://www.cnblogs.com/sunshouguo/p/14844338.html