异步并发任务控制

616 阅读2分钟

前言

假设现在有这么一种场景:现有30个异步请求需要发送,但由于浏览器每次发出请求都会建立TCP连接,不同的浏览器有TCP连接限制,谷歌是建立超过6个之后就会卡顿,所以我们必须将同一时刻并发请求数量控制在6个以内,同时还要尽可能快速的拿到响应结果。

应该怎么做?接下来继续往下看。

实现

  1. 准备数据,用于模式并发数量,下面的相当于同时发出15个请求。
const chunk = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
  1. 模拟请求,通过setTimeout结合随机数控制,模拟不同的请求返回时间。
 function sendRequest(task) {
   return new Promise((resolve, reject) => {
     setTimeout(() => {
       resolve(task)
     }, Math.random() * 2000)
   })
 }
  1. 并发控制并统计累计错误次数,报错3次直接中断请求。
   let errorCount = 0 // 累计报错次数// 并发控制, 错误重试
   function concurrent(chunks = [], limit) {
     return new Promise((resolve, reject) => {
       let len = chunks.length // 记录总任务数
       let count = 0 // 用于记录任务是否执行完成
 ​
       // 启动任务
       const start = async () => {
         const task = chunks.shift() // 拿出一个任务
 ​
         // 如果有任务执行
         if (task) {
           try {
             const ret = await sendRequest(task)
             console.log(ret);
             if (count === len - 1) {
               resolve()
             } else {
               count++
               start()
             }
           } catch (error) {
             // 如果错误请求没超过3次,重新进行请求,超过3次之后退出请求状态
             if (errorCount < 3) {
               start()
             } else {
               console.log('退出请求', error)
               reject()
             }
           }
         }
       }
 ​
 ​
       // 控制最多发送的次数
       while (limit > 0) {
         start()
         limit -= 1
       }
     })
   }

结语

这样我们就实现了异步并发任务控制,并且还完成了错误之后的重试。这道题目呢我想很多同学都或多或少的见过,这其实就是字节的一道面试题。

实现一个批量请求函数 multiRequest(urls, maxNum),要求如下:
• 要求最大并发数 maxNum
• 每当有一个请求返回,就留下一个空位,可以增加新的请求
• 所有请求完成后,结果按照 urls 里面的顺序依次打出

希望我的文章可以帮助xdm,更好的完成异步并发控制的功能。如果文章对你有帮助请帮忙给熊猫小弟点赞 ,关注 + 评论。

熊猫小弟会持续进行技术文章的输出,xdm的点赞就是我坚持下去的动力,感谢大家🙏🙏🙏。