限制请求并发数量的问题

3,315 阅读2分钟

前言

最近在开发项目总结会的时候,老大提出项目首次进入很卡,导致用户反馈不是很理想, 我们就很认真的回了句,页面接口太多了一进来要一大堆接口的等着请求巴拉巴拉的一些.

其实当时脑子是这样的:

image

回座位后就想着是不是可以限制下接口请求的数量,正好网上也有类似的面试题和讨论,就上网看了下并自己总结了下.

思路理解

思路

其实这个问题看着觉得蛮复杂的,仔细想想, 其实就是从外面promisemax 进来,然后循环请求列表,判断是否等于max ,如果等于,则等待列表中有请求执行完,如果不是,则把新的请求放进请求列表里去

流程

  • 根据max值,新建一个请求数组requestArr(长度为max) 或者 传进来一个包含多个请求的数组,并根据 max的长度切割开一个新数组
  • requestArr一项项丢入循环(递归实现),执行完则删除
  • 执行完后先判断requestArr长度是否到达max上限,如果数组已经达到长度上线,则继续执行循环,如有空位再判断是否还存在未加入请求列表的请求,如有则添加到请求数据列表后再执行

代码

image

let requestList = (urls = [], limit = 5) => {
            // 判断urls 是否存在,并且不为null
            if (urls.length === 0 || urls === null) {
                return false
            }
            
            // 深拷贝一份urls,循环用
            let urlsCopy = urls.slice(0)
            let requestArr = []
            if (urls.length < limit) {
                requestArr = urlsCopy
            } else {
                requestArr = urlsCopy.splice(0, limit)
            }
            // 写递归循环请求
            const call = () => {
                // 获取当前触发的请求
               let a = Promise.race(requestArr)
               // 当前请求不管失败还是成功触发判断
               a.then(resolve).catch(reject).finally(() => {
                   // 在数组中删除已经触发的请求
                   requestArr.forEach(item => {
                    requestArr.splice(requestArr.indexOf(a), 1)
                   })
                   // 请求触发后,删除了当前请求,则判断传入的url数组内是否还有未加入的请求
                   // 如果有,则加入,并重新触发循环
                   if (urlsCopy.length) {
                       requestArr.push(urlsCopy.shift())
                       call()
                   }
                   // 触发完成后,判断请求列表内是否还有请求,有则重新进入循环
                   if (requestArr.length) {
                       call()
                   }
               })
            }
        }

上面是一个最简单的请求,没考虑太多,就先写出来试试看能否来限制,并查看实现效果

上面函数

后续思考

继上面的最近实例后,发现在项目上好像并不怎么实用,在想能不能封装axios请求的get、post 方法,可以在一个地方引入使用即可,这就后续有空待研究了

image

参考连接

js如何限制Promise“并发”的数量: