Vue并发队列-最大并发数量限制
需求:
- 设置最大请求数量,当前请求数量,待执行队列
- 调用时,创建一个新任务,然后判断是否达到最大请求数量,若达到则将任务追加到待执行队列,否则,则直接执行该任务。并返回Promise
- 创建任务时,需要返回一个函数,当该任务开始执行则当前数量加一。当任务执行完毕时使用finally,当前数量减一,并从待执行队列中取出新任务执行
实现:
JS版本
/* 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)
}
}
}
TS版本:
export class LimitPromise {
_max: number // 异步任务“并发”上限
_queueList: any[] // 等待执行的任务队列
_count: number // 当前正在执行的任务数量
constructor(maxLimit) {
this._max = maxLimit
this._queueList = []
this._count = 0
}
/**
* 调用器,将异步任务函数和它的参数传入
* @param caller 异步任务函数,它必须是async函数或者返回Promise的函数
* @param args 异步任务函数的参数列表
* @returns {Promise<unknown>} 返回一个新的Promise
*/
call(caller, ...args) {
return new Promise((resolve, reject) => {
// 创建一个任务
const task = () => {
caller(...args)
.then((res) => resolve(res))
.catch((err) => reject(err))
.finally(() => {
// 任务队列的消费区,利用Promise的finally方法,在异步任务结束后,取出下一个任务执行
if (this._queueList.length) {
const nextTask = this._queueList.shift()
nextTask()
this._count--
}
})
}
if (this._count < this._max) {
// 如果异步任务“并发”未达到上限,立刻执行新创建的任务
task()
this._count++
} else {
// 将创建的推进任务队列中
this._queueList.push(task)
}
})
}
// 清空任务队列
clearQueue() {
this._queueList = []
this._count = 0
}
}
使用:
假设我们有一个请求方法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.cnblogs.com/sunshouguo/p/14844338.html
近期评论