SOURCE

console 命令行工具 X clear

                    
>
console
function asyncPool(poolLimit, urls, request) {
  let i = 0; // 已实例化的数量、下标
  const ret = []; // 已发出的promise请求的实例
  const executing = []; // promise请求执行池
  const enqueue = function () {
    // 递归边界处理,urls为空数组或全部处理完
    if (i === urls.length) return Promise.resolve();
    // 取出一个url实例化
    const item = urls[i++];
    // promise then返回值为新promise实例时,相当于return新promise的reslove结果
    const p = Promise.resolve().then(() => request(item));
    // 保存promise实例,最后由promise.all统一收集结果
    ret.push(p);
    // 将执行中的promise实例放入执行池数组
    executing.push(p);
    // promise执行完毕后,从执行池数组中删除
    p.then(() => executing.splice(executing.findIndex(p), 1));
    // 最后返回的promise实例 r
    let r = Promise.resolve();
    // 如果执行池数量达到限制值,则使用Promise.rece, 当某个任务结束之后,就利用递归实例化新的任务
    if (executing.length >= poolLimit) {
      r = Promise.race(executing);
    }
    // 递归,直到遍历完urls, 第一个then
    return r.then(() => enqueue());
  };
  // 第二个then
  return enqueue().then(() => Promise.all(ret));
}

let arr = [];
let index = 0;
while (index < 10) {
  index++;
  arr.push(index);
}

asyncPool(3, arr, (param) => {
  // console.log(param);
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(param);
    }, Math.floor(Math.random() * 5 + 1) * 1000);
  });
})
// 第三个then
.then((res) => {
  console.log("res", res);
});
<div>请查看控制台</div>