使用Promise.any处理前端高并发问题

使用Promise.any处理前端请求高并发之前,首先要弄清楚Promise几个函数的关系;

Promise.all(): 全部子实例(promise对象)成功才算成功,一个子实例失败就算失败

Promise.any(): 有一个子实例(promise对象)成功就算成功,全部子实例失败才算失败

Promise.race(): race是竞赛的意思,即看最先的promise子实例是成功还是失败,则它就与最先的子实例状态相同。

Promise.allSettled(): 所有子实例状态都返回结果,不管子实例是成功还是失败,包装实例才执行,不过状态总是变成成功 。

class PromisePool{
  
  constructor(limit, callback){
    this.limit = limit; // limit为每次的并发量
    this.pool = []; //初始化并发池
    this.callback = callback; //所有任务执行完的回调
    this.urls = []; //urls地址为所有的请求地址数组
  }
  
  start(urls){
    console.time('计时')
    // 首次初始化并发池
    this.urls = urls;
    let len = Math.min(this.urls.length, this.limit);
    let initUrl = this.urls.splice(0, len); //切割之后urls还剩len之后的部分
    
    if (initUrl.length > 0) {
      // 首次把线程池塞满
      for (let i = 0; i < initUrl.length; i++) {
        this.runTask(initUrl[i])
      }
    }
  }

  // 再次往线程池添加任务
  raceTask(race){
    race.then(res => {
      if (this.urls.length > 0) {
        let url = this.urls.shift();
        // 一有一个任务完成,就再塞下一个
        this.runTask(url);
      }
    });  
  }

  runTask(url){
    let task = this.mockFetch(url);
    // this.pool里面的是promise任务数组
    if(this.pool.length < this.limit) {
      this.pool.push(task)
    }
    console.log(this.pool)
    // 利用promise.any方法获取某个任务完成的信号
    let race = Promise.any(this.pool);
    
    // 每个请求结束后,将该promise请求从并发池移除
    // 成功和失败都要执行移除和往并发池添加的动作
    task.then((res) => {
      // console.log('成功:',res);
      this.pool = this.pool.filter((ele) => ele != task);
      this.raceTask(race);
      if (this.pool.length === 0) {
        this.callback('执行完了');
        console.timeEnd('计时')
      }
    }).catch((err) => {
      // console.log('错误:',err)
      this.pool = this.pool.filter((ele) => ele != task);
      this.raceTask(race);
      if (this.pool.length === 0) {
        this.callback('执行完了');
        console.timeEnd('计时')
      }
    })
  }

  // 模拟ajax请求
  mockFetch(param){
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if(param.info !== '2'){
          resolve(param);
        } else{
          reject(param);
        }
      }, 2000);
    })
  }
}

const pool = new PromisePool(5, (res) => {
  console.log(res)
});
const urls = [{
    info: '1',
    time: 2000
  },
  {
    info: '2',
    time: 1000
  },
  {
    info: '3',
    time: 2000
  },
  {
    info: '4',
    time: 2000
  },
  {
    info: '5',
    time: 3000
  },
  {
    info: '6',
    time: 1000
  },
  {
    info: '7',
    time: 2000
  },
  {
    info: '8',
    time: 2000
  },
  {
    info: '9',
    time: 3000
  },
  {
    info: '10',
    time: 1000
  },
  {
    info: '11',
    time: 1000
  },
  {
    info: '12',
    time: 2000
  },
  {
    info: '13',
    time: 2000
  },
  {
    info: '14',
    time: 3000
  },
  {
    info: '15',
    time: 1000
  },
  {
    info: '16',
    time: 1000
  }, 
  {
    info: '17',
    time: 2000
  }, 
  {
    info: '18',
    time: 2000
  }, 
  {
    info: '19',
    time: 3000
  }, 
  {
    info: '20',
    time: 1000
  }
]

pool.start(urls);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值