性能优化第03期 – HTTP请求优化

Chrome 浏览器的请求机制:同一个域名同时最多只能建立 6 个 TCP 连接,也就是说单个域名最大的并发量是 6

如果并发请求达到一定量级的时候,堆积了无数的调用栈就有可能会导致内存溢出

并行请求

  • 使用场景

    将所有请求一次性全部发送出去,然后等待接收全部的结果

    适合请求数固定且不需要按照预期顺序执行异步任务的情况

  • Promise.all方法

    (async () => {
      const [data1, data2, data3] = await Promise.all([
        Promise.resolve(1),
        Promise.resolve(2),
        Promise.resolve(3),
      ])
      .catch(e => {
        console.error(e)
      })
      console.log(`Received data: ${data1}`)
      console.log(`Received data: ${data2}`)
      console.log(`Received data: ${data3}`)
    })()
    复制代码

    如果其中某个异步任务出现异常,则所有任务都会视为失败,此时 Promise 直接进入 rejected 状态

  • Promise.allSettled方法

    (async () => {
      const response = await Promise.allSettled([
        Promise.reject(1),
        Promise.resolve(2),
        Promise.resolve(3),
      ])
      console.log('Received data:', response)
    })()
    复制代码
    [
      { "status": "rejected", "reason": 1 },
      { "status": "fulfilled", "value": 2 },
      { "status": "fulfilled", "value": 3 },
    ]
    复制代码

    无论成功或异常,都将返回对应的状态,由开发者根据业务过滤自己想要的结果

串行请求

  • 使用场景

    按照预期顺序执行异步任务,即等待上一个 await 执行完毕后,再接着执行下一个

    适合请求数固定且需要按照预期顺序执行异步任务的情况

  • for-of循环

    (async () => {
      const promises = [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]
      for (const [index, promise] of promises.entries()) {
        console.log(`Received data: ${await promise}`)
      }
      console.log('Finished')
    })()
    复制代码
  • 异步遍历器

    (async () => {
      const promises = [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]
      try {
        for await (const data of promises) {
          console.log('Received data:', data)
        }
      } catch (e) {
        console.error(e)
      }
      console.log('Finished')
    })()
    复制代码

量化的并发请求数控制

  • 优化场景

    大文件的分片上传请求;批量下载文件的请求

  • 通过while循环实现并发

    const invariable = ({ list = [], limit = 3, singleComplete = () => {} }) => {
      return new Promise((resolve, reject) => {
        let completeCount = 0, total = list.length
        limit = total > limit ? limit : total
        while(limit--) {
          const { url, data } = list.shift()
          recursion(url, data)
        }
      })
    }
    复制代码
  • 通过递归实现请求数控制

    const recursion = (url, data) => {
      fetchFileStream(url).then(blob => {
         singleComplete({ data, response: blob })
         completeCount += 1
         if (list.length) {
           const { url, data } = list.shift()
           recursion(url, data)
         } else {
           completeCount === total && resolve(true)
         }
       })
     }
    复制代码

往期回顾

性能优化第01期 – 建立性能知识体系

性能优化第02期 – DNS解析及其优化

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享