手写系列 - Promise 控制请求并发

869 阅读2分钟

做了这么一件事:Promise处理高并发问题, 有 100 条数据,我们的带宽为10, 跑满带宽

//模拟100条数据
const message = new Array(100).fill('');
for (let i = 0; i < 100; i++) {
  message[i] = '第' + i + '条数据';
}

function axiosGet(index) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(message[index])
    }, 1000 * Math.random())

  })
}

// async + promise 方案
async function asyncProcess(max = 10) {
  const task = []; //并发池
  const res = [];

  for (let i = 0; i < 100; i++) {
    const curr = axiosGet(i).then(value => {
      console.log(value, task.length);
      res.push(value);
      //请求结束后将该Promise任务从并发池中移除
      task.splice(task.indexOf(curr), 1)
    });
    //每当并发池跑完一个任务,就再塞入一个任务
    task.push(curr);
    //利用Promise.race方法来获得并发池中某任务完成的信号
    //跟await结合当有任务完成才让程序继续执行,让循环把并发池塞满
    if (task.length === max) {
      await Promise.race(task)
    }
  }
  await Promise.allSettled(task)
  return res;

}

asyncProcess().then(value => {
  console.log(value)
})

0条数据 107条数据 104条数据 105条数据 102条数据 106条数据 1014条数据 109条数据 1013条数据 1011条数据 101条数据 1010条数据 108条数据 1019条数据 10
........
第78条数据 996条数据 898条数据 781条数据 689条数据 587条数据 499条数据 394条数据 293条数据 1
[  '第0条数据',  '第7条数据',  '第4条数据',  '第5条数据',  '第2条数据',  '第6条数据',  '第14条数据', '第9条数据',  '第13条数据', '第11条数据',  '第1条数据',  '第10条数据', '第8条数据',  '第19条数据', '第3条数据',  '第15条数据', '第16条数据', '第12条数据', '第25条数据', '第22条数据',.........................  '第90条数据', '第78条数据', '第96条数据', '第98条数据', '第81条数据',  '第89条数据', '第87条数据', '第99条数据', '第94条数据', '第93条数据']