前端性能优化--控制请求并发数

250 阅读2分钟

控制请求并发数

需求:有时候你会遇到这么一个需求,比如资源的切片传输,短时间内要连续调用接口,假如该资源需要100个接口调用才能完成传输,但同时调用100个接口,带宽资源也顶不住;又比如你在做某个图表,需要重复调用几十个接口做不同模块的渲染只是入参不同,对服务器不太友好;这时候就需要通过接口并发,限制同一时间请求的接口数量,话不多说直接上码!

image.png

  • 首先确定入参,我们接受一个请求地址的数组,自动的将该数组里的地址取出进行请求;同时接收一个最大请求的并发数(根据业务和性能自行控制)。
  • 出参:我们希望当所有请求完成的时候返回一个结果数组,并且结果数组要对应请求地址的位置,比如请求地址A的位置为0,返回的结果也应存放在结果数组的0位置

🤔思考:如何取出请求数组的地址进行请求呢?

​ 这里我定义了一个指针index,指针根据请求次数自增,当指针超出数组边界停止请求

/**
 * 
 * @param {请求的数组} urls 
 * @param {请求的并发数} maxNum 
 * 同时执行maxNum个请求,完成一个就再从urls拿一个继续请求,等所有请求完成之后返回结果数组
 */
export const concurrent = (urls, maxNum) => {
  if (!Array.isArray(urls) || !urls?.length) return new Promise.resolve([])
  return new Promise((resolve, reject) => {
    let index = 0 // 指向下一次请求
    let result = [] // 存放请求结果
    let count = 0 //请求完成的数量
    const _request = async () => {
      const i = index
      const url = urls[index]
      index++
      try {
        const resp = await request({ url, })
        result[i] = resp
      } catch (error) {
        result[i] = error
      } finally {
        count++
        if (count === urls.length) {
          resolve(result) // 所有请求完成
        }
        if (index < urls?.length) {
          _request()
        }
      }
    }
    // 最大请求并发数应该取数组真实长度和并发数的最小值
    for (let j = 0; j < Math.min(urls.length, maxNum); j++) {
      _request()
    }
  })
}