自定义Promise

class Promise {
  // 构造方法
  constructor(executor) {
    // resolve函数---里面还需要声明形参去接收实参

    // 给实例对象的身上添加属性,直接通过this强行复制的方式去添加,这里的this就指的是新创建(new出来的)的实例对象
    this.PromiseState = "pending";
    this.PromiseResult = null;
    // 声明属性用来保存then方法中的回调函数
    this.callBacks = [];

    // 解决下方this指向问题,可以在这里先把this的指向保存下来
    const that = this;
    // const _this = this;
    // const self = this; //三种保存this值的常见写法
    function resolve(data) {
      // 判断Promise实例对象的状态(状态变为成功或者失败就不能再次改动)
      if (that.PromiseState !== "pending") return;
      // 1.修改对象的状态(PromiseState)
      // 注意:这里的this指向的不是新new出来实例对象,而是指向全局的Window对象(所以要提前把this的值保存下来)
      that.PromiseState = "fulfilled"; //或者为resolve(意思都一样)
      // 2.修改对象结果值(PromiseResult)
      that.PromiseResult = data;
      // 调用成功的回调函数
      that.callBacks.forEach((item) => {
        setTimeout(() => {
          //加定时器让回调函数变为异步操作
          item.onResolved(data); //forEach不会遍历数组元素为empty(空)的数组,所以加不加判断条件都不会影响性能
        });
      });
    }
    // reject函数---里面还需要声明形参去接收实参
    function reject(data) {
      // 判断Promise实例对象的状态(状态变为成功或者失败就不能再次改动)
      if (that.PromiseState !== "pending") return;
      // 1.修改对象的状态(PromiseState)
      that.PromiseState = "rejected";
      // 2.修改对象结果值(PromiseResult)
      that.PromiseResult = data;
      // 调用失败的回调函数
      that.callBacks.forEach((item) => {
        setTimeout(() => {
          item.onRejected(data);
        });
      });
    }

    // 同步调用(执行器函数-executor)
    try {
      executor(resolve, reject);
    } catch (error) {
      // 修改Promise实例对象的状态为失败
      reject(error);
    }
  }

  // then方法的封装
  then(onResolved, onRejected) {
    const that = this;

    // 判断回调函数参数是否传递的是一个函数,如果不是一个函数,就给他添加一个默认值---值为函数
    if (typeof onResolved !== "function") {
      onResolved = (value) => value; //value=>{return value} ES6
    }

    if (typeof onRejected !== "function") {
      onRejected = (reason) => {
        throw reason;
      };
    }
    return new Promise((resolve, reject) => {
      // 封装函数
      function callBack(type) {
        try {
          // 在这里还有传入实参,实参为Promise实例对象成功之后的结果值
          // 获取成功函数的执行结果
          let result = type(that.PromiseResult); //this指向有问题,在函数内部直接调用,指的是Window

          // 判断result是不是Promise的实例对象
          if (result instanceof Promise) {
            //  如果是Promise类型的对象
            result.then(
              (v) => {
                resolve(v);
              },
              (r) => {
                reject(r);
              }
            );
          } else {
            // 结果的对象状态为成功
            resolve(result);
          }
        } catch (error) {
          reject(error);
        }
      }

      // 调用回调函数并且加上判断条件(判断Promise实例对象身上的PromiseState属性)
      // 这里的this指的是Promise实例对象(函数包裹第一层的时候里面的this指向的是实例对象,第二层指向的是Window,除非第二层写箭头函数,箭头函数没有自己的this,所以this指向的就是外部的定义时的this,就是Promise实例对象),标准说法为构造函数中的this,后期谁调用指谁
      if (this.PromiseState === "fulfilled") {
        setTimeout(() => {
          //加定时器更改回调函数为异步执行
          callBack(onResolved);
        });
      }

      if (this.PromiseState === "rejected") {
        setTimeout(() => {
          callBack(onRejected);
        });
      }

      // 判断pending状态
      if (this.PromiseState === "pending") {
        // 保存回调函数
        this.callBacks.push({
          // ES6简写
          // onResolved, //相当于onResolved:onResolved
          // onRejected, //相当于onRejected:onRejected

          onResolved: function () {
            callBack(onResolved);
          },
          onRejected: function () {
            callBack(onRejected);
          },
        });
      }
    });
  }

  // catch方法的封装
  catch(onRejected) {
    return this.then(undefined, onRejected);
  }

  // resolve方法的封装
  static resolve(value) {
    return new Promise((resolve, reject) => {
      if (value instanceof Promise) {
        value.then(
          (v) => {
            resolve(v);
          },
          (r) => {
            reject(r);
          }
        );
      } else {
        resolve(value);
      }
    });
  }

  // reject方法的封装
  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    });
  }

  // all方法的封装
  static all(promises) {
    // 声明一个变量,用来判断promises数组里的Promise对象状态十分都为成功
    let count = 0;
    // 声明一个变量,用来保存成功的结果,结果是一个数组
    let arr = [];

    // 结果为Promise的对象
    return new Promise((resolve, reject) => {
      // 遍历---这里的变量i必须使用let声明,不然i会被全局污染
      for (let i = 0; i < promises.length; i++) {
        // parmises[i]是其中的一个Promise对象
        promises[i].then(
          (v) => {
            // 得知对象的状态是成功的
            // 如果每一个Promise对象的状态都是成功的,才能去执行resolve函数
            count++;
            // 将当前Promise对象的结果存入到数组中
            // arr.push(v);这种方法保存结果有点bug,异步的时候会导致顺序跟数组里面传进来Promise对象顺序不一致
            arr[i] = v;
            // 判断:如果count的值等于promises数组的长度,就说明这个promises数组里的Promise数组状态都为成功
            if (count === promises.length) {
              // 修改状态
              resolve(arr);
            }
          },
          (r) => {
            reject(r);
          }
        );
      }
    });
  }

  // race方法的封装
  static race(promises) {
    return new Promise((resolve, reject) => {
      for (let i = 0; i < promises.length; i++) {
        promises[i].then(
          (v) => {
            // 修改返回对象的状态为成功
            resolve(v);
          },
          (r) => {
            // 修改返回对象的状态为失败
            reject(r);
          }
        );
      }
    });
  }
}
posted @ 2021-12-27 21:54  问某完红  阅读(62)  评论(0编辑  收藏  举报