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

915 阅读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条数据 10
第7条数据 10
第4条数据 10
第5条数据 10
第2条数据 10
第6条数据 10
第14条数据 10
第9条数据 10
第13条数据 10
第11条数据 10
第1条数据 10
第10条数据 10
第8条数据 10
第19条数据 10
........
第78条数据 9
第96条数据 8
第98条数据 7
第81条数据 6
第89条数据 5
第87条数据 4
第99条数据 3
第94条数据 2
第93条数据 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条数据']