前端如何实现并发请求数量控制?

前言

前端并发请求数量控制是指在客户端(通常是在浏览器中)管理和控制同时发出的异步请求的数量。在进行网络请求,如使用 AJAX 与服务器交互时,可能会有多个请求同时发送。如果不加以控制,大量并发的请求可能会导致服务器压力过大,或者在客户端造成性能问题。

场景

公司有一个发票管理模块,实现了用户上传单张发票,系统进行切割,ocr识别,验真,验重,保存。现在需要实现批量操作:同时上传多张发票图片,进行自动进行上述操作。并且完成一张即在列表中展示一张出来。最终定的方案是前端循环去一次调用上述流程的接口,因此这里就需要实现一个线程池,,请求中的数据达到最大值时,将所有请求添加到队列中进行排队,每当有一个请求返回,就留下一个空位,可以去处理队列中的首位执行请求。

实现

js 复制代码
class LimitPromise{
    constructor(max){
        this._max = max || 6 // 最大执行数量
        this._count = 0 // 当前执行的数量
        this._taskQueue = [] // 队列   
        this.instance = null // 实例 单例模式
    }
    run(caller){
        return new Promise((resolve, reject)=>{
            const task = this._createTask(caller, resolve, reject)
            // 当前执行的数量 > 最大执行数量,就加入队列排队;否则直接执行
            if(this._count >= this._max){
                this._taskQueue.push(task)
            }else {
                task()
            }
        })   
    }
    _createTask(caller, resolve, reject){
        return ()=> {
            caller().then(res =>{
                resolve(res)
            }).catch(err => {
                reject(err)
            }).finally(()=>{
                // 执行完成
                this._count--
                if(this._taskQueue.length > 0){
                    // 取出队列中的首位执行
                    const task= this._taskQueue.shift()
                    task()
                }
            })
            this._count++
        }
    }
    static getInstance(max){
        if(!this.instance){
            this.instance = new LimitPromise(max)
        }
        return this.instance
    }
}

如何使用

js 复制代码
// 构获取实例
const limitPromise = LimitPromise.getInstance(3)
const asyncTask = (params) => {
   return new Promise((resolve, reject)=>{
        setTimeout(() => {
            if (params % 2 == 0) {
                resolve({
                    tag:'成功了', params
                })
            } else {
                reject({
                    tag:'失败了', params
                })
            }
        }, 1000)
    })
}

for(let i=0; i<= 100; i++){
    limitPromise.run(() => asyncTask(i)).then(
        result => {
            console.log('result', result)
        },
        error => {
            console.log('error', error)
        }
    )
}
相关推荐
y先森3 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy3 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189113 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿5 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡6 小时前
commitlint校验git提交信息
前端
虾球xz6 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇6 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒6 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员6 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐6 小时前
前端图像处理(一)
前端