• 【JS Promise】手写实现 promise.all 和promise.race 方法


    promise.all:只要任何一个输入的 promise 的 reject 回调执行或者输入不合法的 promise 就会立即抛出错误,并且 reject 的是第一个抛出的错误信息。若没有失败的,则最终返回一个包含所有成功结果的数组

    promise.race:一旦迭代器中的某个 promise resolved或rejected,返回的 promise 就会resolved或rejected。

    在实现之前,先来体验一下promise.allpromise.race的使用:

    const p1 = Promise.resolve(1);
    const p2 = Promise.resolve(Promise.resolve(2));
    const p3 = Promise.resolve(Promise.reject(3));
    const p4 = new Promise((resolve) => {
      setTimeout(() => {
        resolve(4);
      }, 1000);
    });
    
    Promise.all([p4, p1, p2]).then(
      (value) => {
        console.log('res1 value:', value);
      },
      (reason) => {
        console.log('res1 reason:', reason);
      },
    );
    
    Promise.all([p1, p2, p3, p4]).then(
      (value) => {
        console.log('res2 value:', value);
      },
      (reason) => {
        console.log('res2 reason:', reason);
      },
    );
    
    Promise.race([p4, p1, p3, p2]).then(
      (value) => {
        console.log('res3 value:', value);
      },
      (reason) => {
        console.log('res3 reason:', reason);
      },
    );
    
    /* 执行结果
    res2 reason: 3
    res3 value: 1
    res1 value: [ 4, 1, 2 ]
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    1. promise.all实现

    实现的大致思路如下:

    • 返回一个新的promise对象
    • 遍历任务数组
      • 若前任务成功,则将成功的结果暂时存到对应的结果数组中的位置
      • 若失败,则直接reject即可
    • 当成功的任务数和总任务数一致时,将结果数组resolve出去
    const pAll = (promises) => {
    
      // 保存所有成功结果的数组
      const values = [];
      // 成功的次数
      let successCount = 0;
    
      // 返回一个promise对象
      return new Promise((resolve, reject) => {
    
        // 遍历异步任务数组
        promises.forEach((p, index) => {
    
          /**
           * 这里用 Promise.resolve()包装一下p是考虑promises中的值有可能不是promise对象,
           * 例如普通的值 pAll([p1, p2, 2, 'hello'])
           */
          Promise.resolve(p).then(
            (value) => {
    
              /**
               * 注意这里不要用 values.push(value) 这种方式来将成功的值放到数组中
               * 由于promises数组中的异步任务并不一定是按顺序完成的
               * 应该使用 values[index] = value 这种方式
               */
              values[index] = value;
              successCount += 1;
              
              // 当成功的次数等于promises异步任务数组的长度时,将最终的结果resolve出去
              if (successCount === promises.length) {
                resolve(values);
              }
            },
            (reason) => {
    
              // 当遇到一个异步任务失败的时候,直接reject即可,后续的任务再失败就不用考虑了
              reject(reason);
            },
          );
        });
      });
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    可以测试一下我们实现的代码:

    pAll([p4, p1, p2]).then(
      (value) => {
        console.log('res value:', value);
      },
      (reason) => {
        console.log('res reason:', reason);
      },
    );
    
    
    /* 执行结果
    res value: [ 4, 1, 2 ]
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2. promise.race实现

    promise.race的实现相对来说就更简单一些了。

    const pRace = (promises) => {
      return new Promise((resolve, reject) => {
        promises.forEach((p) => {
          p.then(
            (value) => {
              resolve(p);
            },
            (reason) => {
              reject(reason);
            },
          );
        });
      });
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    同样测试一下代码:

    pRace([p4, p1, p3, p2]).then(
      (value) => {
        console.log('value:', value);
      },
      (reason) => {
        console.log('reason:', reason);
      },
    );
    
    /* 执行结果
    value: 1
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    研发说:安全是软件开发的生命线
    CV计算机视觉每日开源代码Paper with code速览-2023.10.10
    一本通2059;买笔
    全连接网络实现回归【房价预测的数据】
    SpringBoot面试题及答案 110道(持续更新)
    Flask 使用 JWT(二)
    EasyPOI实现excel文件导出
    C++面试经典题目汇总
    在uniapp和微信小程序中onshow和onload的区别
    10个好用的Mac数据恢复软件推荐—恢复率高达99%
  • 原文地址:https://blog.csdn.net/baidu_36511315/article/details/126083234