+
80
-

js如何控制ajax请求的并发数限流?

请问js如何控制ajax请求的并发数限流?


网友回复

+
0
-

由于浏览器并发的请求数是6,如果超过就阻塞了,我们可以写一个缓存器, 把那些还没有发送的请求存起来

设置一个上限值,上限肯定比 6 小, 当正在请求数大于这个数时, 不再请求,具体代码如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    
  </head>
  <body>
    <script>
      class LimitRequest {
        // 限制同时请求的数量
        limitCount = 0
        // 缓存还没有发送的请求
        cacheRequest = []
        // 当前正在请求的数量
        currentRequest = 0
        constructor(limitCount) {
          this.limitCount = +limitCount || 3
        }
        /**
         * 新增请求
         * @param {*} fn
         */
        addRequest(fn) {
          if (typeof fn !== 'function') {
            console.log('addRequest添加请求需要传入函数')
            return
          }
          // 把这个请求缓存起来
          this.cacheRequest.push(fn)
          // 修改, 这里不去调用了, 留着用户自己在合适的时机调用
        }
        /**
         * 从缓存中拿出一条请求, 发送
         */
        async request() {
          if (this.currentRequest >= this.limitCount) {
            // 如果当前请求数量超出了限制, 不再发送新的请求
            return
          }
          // 当前正在请求的数量加一
          this.currentRequest++
          // 这里是用户主动调的, 所以一次要请求到上限
          this.request()
          try {
            // 拿出缓存的请求
            const fn = this.cacheRequest.shift()
            // 发送请求
            await fn()
          } catch (err) {
            console.log('执行fn报错', err)
          } finally {
            // 请求结束, 当前正在发送的请求减一
            this.currentRequest--
            if (this.cacheRequest.length) {
              // 空出一个名额, 并且还有请求, 可以再次请求
              this.request()
            }
          }
        }
      }
      const limitRequest = new LimitRequest(3)
      for (let i = 0; i < 2000; i++) {
        limitRequest.addRequest(async () => {
          await fetch(`get?index=${i}`)
        })
      }
      setTimeout(() => {
        // 在3秒之后, 浏览器空闲了, 发送请求
        limitRequest.request()
      }, 3000)
    </script>
  </body>
</html>

我知道答案,我要回答