背景
接手了一个老项目,启动后首页打开请求三十几个接口,人都崩溃。只能想办法写promise优化下,现在基本上前端项目都是通过axios来实现异步请求的封装,异步编程。
明确概念
这里有几个概念需要明确一下
- 并发:并发是多个任务同时交替的执行(因为cpu执行指令的速度非常之快,它可以不必按顺序一段代码一段代码的执行,这样效率反而更加低下),这样看起来就是一起执行的,所以叫并发。
 
- 并行:可以理解为多个物理cpu或者有分布式系统,是真正的’同时’执行
 
- 并发控制:意思是多个并发的任务,一旦有任务完成,就立刻开启下一个任务
 
- 切片控制:将并发任务切片的分配出来,比如10个任务,切成2个片,每片有5个任务,当前一片的任务执行完毕,再开始下一个片的任务,这样明显效率没并发控制那么高了
 
思路
首先执行能执行的并发任务,根据并发的概念,每个任务执行完毕后,捞起下一个要执行的任务。
将关键步骤拆分出合适的函数来组织代码
- 循环去启动能执行的任务
 
- 取出任务并且推到执行器执行
 
- 执行器内更新当前的并发数,并且触发捞起任务
 
- 捞起任务里面可以触发最终的回调函数和调起执行器继续执行任务
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
   | 
  sendRequest(
      [() => request('1'),
      () => request('2'),
      () => request('3'),
      () => request('4')],
      3, 
      (res) => {
          console.log(res)
      })
 
  function request(url, time = 1) {
      return new Promise((resolve, reject) => {
          setTimeout(() => {
              console.log('请求结束:' + url);
              if (Math.random() > 0.5) {
                  resolve('成功')
              } else {
                  reject('错误;')
              }
          }, time * 1e3)
      }) }
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
   | async function sendRequest(requestList,limits,callback){
      
      const promises = []
      
      const pool = new Set() 
      
      for(let request of requestList){
          
          if(pool.size >= limits){
              
 
              await Promise.race(pool)
              .catch(err=>err)
          }
          const promise = request()
          
          const cb = ()=>{
              pool.delete(promise)
          }
          
          promise.then(cb,cb)
          pool.add(promise)
          promises.push(promise)
      }
      
      
 
      Promise.allSettled(promises).then(callback,callback)
  }
  |