美文网首页
Promise.all 并发限制

Promise.all 并发限制

作者: Yong_bcf4 | 来源:发表于2020-07-07 19:45 被阅读0次

    Promise.all 并发限制

    简介

    Promise.all 可以保证,promises 数组中所有 promise 对象都达到 resolve 状态,才执行 then 回调。 这时候考

    虑一个场景:如果你的 promises 数组中每个对象都是 http 请求,或者说每个对象包含了复杂的调用处理。而

    这样的对象有几十万个。 那么会出现的情况是,你在瞬间发出几十万 http 请求(tcp 连接数不足可能造成等

    待),或者堆积了无数调用栈导致内存溢出。 这时候,我们就需要考虑对 Promise.all 做并发限制。

    Promise.all 并发限制指的是,每个时刻并发执行的 promise 数量是固定的,最终的执行结果还是保持与原来的

    Promise.all 一致。

    现在已经有的成熟解决方案:tiny-async-pool、es6-promise-pool、p-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);

    }

    );

    相关文章

      网友评论

          本文标题:Promise.all 并发限制

          本文链接:https://www.haomeiwen.com/subject/airhcktx.html