Promise.all 并发限制

Promise.all 并发限制

参考链接

简介

Promise.all 可以保证,promises 数组中所有 promise 对象都达到 resolve 状态,才执行 then 回调。
这时候考虑一个场景:如果你的 promises 数组中每个对象都是 http 请求,或者说每个对象包含了复杂的调用处理。而这样的对象有几十万个。
那么会出现的情况是,你在瞬间发出几十万 http 请求(tcp 连接数不足可能造成等待),或者堆积了无数调用栈导致内存溢出。
这时候,我们就需要考虑对 Promise.all 做并发限制。
Promise.all 并发限制指的是,每个时刻并发执行的 promise 数量是固定的,最终的执行结果还是保持与原来的 Promise.all 一致。

现在已经有的成熟解决方案:tiny-async-pooles6-promise-poolp-limit

实现思路

主要是通过第三方插件,来控制异步函数的执行。

代码参考:tiny-async-pool 源码。相比于其主功能函数做了以下优化:

1、使用方式更接近原本的 Promise.all

function promsie1() {}
function promsie2() {}
function promsie3() {}

Promise.all([promsie1(), promsie2(), promsie3()]);
PromiseLimit([promsie1, promsie2, promsie3]);

2、当执行过程中某个 promise 返回 reject 则停止后续的 promise 执行。

代码

function PromiseLimit(funcArray, limit = 5) {
  let i = 0;
  const result = [];
  const executing = [];
  const queue = function() {
    if (i === funcArray.length) return Promise.all(executing);
    const p = funcArray[i++]();
    result.push(p);
    const e = p.then(() => executing.splice(executing.indexOf(e), 1));
    executing.push(e);
    if (executing.length >= limit) {
      return Promise.race(executing).then(
        () => queue(),
        e => Promise.reject(e)
      );
    }
    return Promise.resolve().then(() => queue());
  };
  return queue().then(() => Promise.all(result));
}

效果演示

// 测试代码
const result = [];
for (let index = 0; index < 10; index++) {
  result.push(function() {
    return new Promise((resolve, reject) => {
      console.log("开始" + index, new Date().toLocaleString());
      setTimeout(() => {
        resolve(index);
        console.log("结束" + index, new Date().toLocaleString());
      }, parseInt(Math.random() * 10000));
    });
  });
}

PromiseLimit(result).then(data => {
  console.log(data);
});

在这里插入图片描述

// 修改测试代码 随机失败或者成功
const result = [];
for (let index = 0; index < 10; index++) {
  result.push(function() {
    return new Promise((resolve, reject) => {
      console.log("开始" + index, new Date().toLocaleString());
      setTimeout(() => {
        if (Math.random() > 0.5) {
          resolve(index);
        } else {
          reject(index);
        }
        console.log("结束" + index, new Date().toLocaleString());
      }, parseInt(Math.random() * 1000));
    });
  });
}
PromiseLimit(result).then(
  data => {
    console.log("成功", data);
  },
  data => {
    console.log("失败", data);
  }
);

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值