手写 Promise

138 阅读2分钟

Promise.all()

Promise.all() 方法接收一个 promise 的 iterable 类型(注:Array,Map,Set都属于ES6的iterable类型)的输入,并且只返回一个Promise实例,那个输入的所有 promise 的 resolve 回调的结果是一个数组。这个Promise的 resolve 回调执行是在所有输入的 promise 的 resolve 回调都结束,或者输入的 iterable 里没有 promise 了的时候。它的 reject 回调执行是,只要任何一个输入的 promise 的 reject 回调执行或者输入不合法的 promise 就会立即抛出错误,并且reject的是第一个抛出的错误信息。

用人话来说就是 Promise.all([p1, p2, p3]) 当 p1, p2, p3 全部返回 resolve 时,才会 resolve,反之就返回 reject

Premise.all() 例子
    const p1 = Promise.resolve("p1");

    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("p2 延时一秒");
      }, 1000);
    });

    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("p3 延时两秒");
      }, 2000);
    });

    const p4 = Promise.reject("p4 rejected");

    const p5 = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject("p5 rejected 延时1.5秒");
      }, 1500);
    });
    
    // 注意这里的 p4 和 p5 因为没有 .catch 会导致报错,直到在 Promise.all() 内部使用之后才会解除报错
    
    
    // 所有Promise实例都成功
    Promise.all([p1, p2, p3])
      .then((res) => {
        console.log(res);
      })
      .catch((err) => console.log(err)); // 2秒后打印 [ 'p1', 'p2 延时一秒', 'p3 延时两秒' ]

    // 一个Promise实例失败
    Promise.all([p1, p2, p4])
      .then((res) => {
        console.log(res);
      })
      .catch((err) => console.log(err)); // p4 rejected

    // 一个延时失败的Promise
    Promise.all([p1, p2, p5])
      .then((res) => {
        console.log(res);
      })
      .catch((err) => console.log(err)); // 1.5秒后打印 p5 rejected

    // 两个Promise实例失败
    Promise.all([p1, p5, p4])
      .then((res) => {
        console.log(res);
      })
      .catch((err) => console.log(err)); // p4 rejected
  
    // 注意:reject 会抛出第一个错误,但是跟数组顺序无关,因为 p4 先执行,所以无论如何都是抛出 p4 的错误

手写 Promise.all() 例子

    Promise.myAll = (promises) => {
      return new Promise((resolve, reject) => {
        // 计数器
        let count = 0;
        // 存放结果
        let arr = [];
        const len = promises.length;
        if (len === 0) {
          return resolve([]);
        }
        promises.forEach((item, i) => {
          console.log("item:", item);
          // 注意有的数组项有可能不是Promise,需要手动转化一下
          Promise.resolve(item)
            .then((res) => {
              count += 1;
              // 收集每个Promise的返回值
              arr[i] = res;
              // 这里设置 count === len 为的就是循环所有的 Promise 都为 fulfiled 成功状态,那么将返回的Promise结果设置为result
              if (count === len) {
                resolve(arr);
              }
              // 监听数组项中的Promise catch只要有一个失败,那么我们自己返回的Promise也会失败
            })
            .catch(reject);
        });
      });
    };
    
    Promise.myAll([p1, p2, p3])
      .then((res) => {
        console.log("res:", res);
      })
      .catch((err) => {
        console.log("err:", err);
      });

    Promise.myAll([p1, p2, p5])
      .then((res) => {
        console.log("res:", res);
      })
      .catch((err) => {
        console.log("err:", err);
      });

    Promise.myAll([p1, p5, p4])
      .then((res) => {
        console.log("res:", res);
      })
      .catch((err) => {
        console.log("err:", err);
      });

后续更新......

另:我这个其实也是看了很多其他大佬写的,我为了以防万一,自己写一份留备份罢了