相关文章推荐
  • 用一个数组存放所有 Promise 任务,一个集合存放正在执行的 Promise 任务
  • queue 函数,递归执行,当数组遍历完全后,退出
  • queue 函数内部, array[i++]() 获取当前函数并执行,实例化出一个 promise ,此时 promise 开始运行
  • 将此 proimse 添加到 executing 集合,且同时添加到 result 数组中
  • promise 执行完成时,又会从 executing 集合中删除,保证 executing 集合中的 promise 都是正在执行的任务
  • 对比 executing 长度,如果长度大于等于限制,就用 race 等一个任务执行完,再递归调用 queue ,如果没有超出限制,就直接递归调用 queue
  • 最后,用 Promise.all result 数组中的所有结果输入到 then 方法中,如果 result 中有失败的 promise ,则会终止后续的 promise
  • function limitPromise(promiseFnList, start = 0, limit = 5) {
        const result = [];  // 存储所有的 Promise 任务
        const executing = new Set();  // 正在执行的 Promise 对象
        let i = start;
        const queue = () => {
            // 边界条件:如果 promises 长度为 0,或 i 到达末尾,就返回一个空的 promise
            if (i >= promiseFnList.length) return Promise.resolve();
            // 拿到一个 promise并运行,设置运行完成后从 executing 集合中删除
            const p = promiseFnList[i++]().finally(() => executing.delete(p));
            // 将运行中的 promise 添加到 executing 集合
            executing.add(p);
            // 并同时添加到 result 数组
            result.push(p);
            // 使用 Promise.race,每当 executing 数组中 promise 数量低于 limit,就实例化新的 promise 并执行
            // const r = executing.size >= limit ? Promise.race(executing) : Promise.resolve();
            // 递归,直到遍历完 promises
            // return r.then(() => queue());
            // 或者一步到位
            return executing.size >= limit ? Promise.race(executing).then(() => queue()) : queue();
        // 最后,用 Promise.all 将 result 中的结果输出,其会等待最后一批执行中的 promise 状态变为完成后才能进入 then 方法
        return queue().then(() => Promise.all(result));
    function fakePromise(url, time, success = true) {
        return function() {
            return new Promise((resolve, reject) => {
                console.log('开始' + url);
                setTimeout(() => {
                    if (success) resolve(`收到来自${url}的相应!`);
                    else reject(`${url}失败!`);
                }, time * 1000);
    const promiseFnList = [
        fakePromise('1', 1, false),
        fakePromise('2', 3),
        fakePromise('3', 2),
        fakePromise('4', 1),
        fakePromise('5', 1),
        fakePromise('6', 4),
        fakePromise('7', 4),
        fakePromise('8', 3),
        fakePromise('9', 3),
        fakePromise('10', 1),
    // 从下标为 3 的项开始,最大并发数为 2
    limitPromise(promiseFnList, 3, 2).then(res => console.log(res), err => console.log(err));
      

    版权

    本作品采用 CC BY-NC-ND 4.0 授权。
     
    推荐文章