手动实现Promise核心原理及其方法

/**
 * executor:执行器,会立即执行
 * 接受两个方法作为参数:
 *  resolve
 *  reject
 */

/**
 * 定义状态
 */
const PENDING = "PENDING"; // 等待
const FULFILLED = "FULFILLED"; // 成功
const REJECTED = "REJECTED"; // 失败

class MyPromise {
  constructor(executor) {
    try {
      // 执行器方法立即执行
      executor(this.resolve, this.reject);
    } catch (error) {
      this.reject(error);
    }
  }
  /**
   * 定义实例属性
   */
  // status promise状态 默认值为PENDING
  status = PENDING;

  // value 成功之后的值 默认值为undefined
  value = undefined;

  // reason 失败之后的值 默认值为undefined
  reason = undefined;

  // resolveCallbacks 成功回调
  resolveCallbacks = [];

  // onRejectCallbacks 成功回调
  rejectedCallbacks = [];

  /**
   * resolve方法
   * 修改promise状态
   * 保存成功之后的值
   * @param {*} value 成功的值
   */
  resolve = (value) => {
    if (this.status === PENDING) {
      // 将状态更改为成功
      this.status = FULFILLED;

      // 保存成功之后的值
      this.value = value;

      // 执行成功的回调
      this.resolveCallbacks.forEach((callback) => callback());
    }
  };

  /**
   * reject方法
   * 修改promise状态
   * 保存失败之后的值
   * @param {*} reason 失败的原因
   */
  reject = (reason) => {
    if (this.status === PENDING) {
      // 将状态更改为失败
      this.status = REJECTED;

      // 保存失败之后的值
      this.reason = reason;

      // 执行失败的回调
      this.rejectedCallbacks.forEach((callback) => callback());
    }
  };

  /**
   * then方法
   * @param {*} onFulFilled 成功的回调方法
   * @param {*} onRejected 失败的回调方法
   * @returns 返回新的promise对象
   */
  then(onFulFilled, onRejected) {
    onFulFilled =
      typeof onFulFilled === "function" ? onFulFilled : (value) => value;
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (reason) => {
            throw reason;
          };

    const promise2 = new MyPromise((resolve, reject) => {
      // 判断状态
      if (this.status === PENDING) {
        // 保存成功的回调
        this.resolveCallbacks.push(() => {
          /**
           * callbackValue 为上一个then成功方法的返回值
           * 判断callbackValue的返回值
           * 如果是普通值则直接调用resolve
           * 如果是promise 根据promise对象返回的结果决定调用resolve或者reject
           * setTimeout 异步代码执行为了拿到promise2
           */
          setTimeout(() => {
            try {
              const callbackValue = onFulFilled(this.value);
              resolvePromise(promise2, callbackValue, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });

        // 保存失败的回调
        this.rejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const callbackValue = onRejected(this.reason);
              resolvePromise(promise2, callbackValue, resolve, reject);
            } catch (error) {
              reject(error);
            }
          }, 0);
        });
      }

      if (this.status === FULFILLED) {
        /**
         * callbackValue 为上一个then成功方法的返回值
         * 判断callbackValue的返回值
         * 如果是普通值则直接调用resolve
         * 如果是promise 根据promise对象返回的结果决定调用resolve或者reject
         * setTimeout 异步代码执行为了拿到promise2
         */
        setTimeout(() => {
          try {
            const callbackValue = onFulFilled(this.value);
            resolvePromise(promise2, callbackValue, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }

      if (this.status === REJECTED) {
        /**
         * callbackValue 为上一个then成功方法的返回值
         * 判断callbackValue的返回值
         * 如果是普通值则直接调用resolve
         * 如果是promise 根据promise对象返回的结果决定调用resolve或者reject
         * setTimeout 异步代码执行为了拿到promise2
         */
        setTimeout(() => {
          try {
            const callbackValue = onRejected(this.reason);
            resolvePromise(promise2, callbackValue, resolve, reject);
          } catch (error) {
            reject(error);
          }
        }, 0);
      }
    });
    return promise2;
  }

  /**
   * finally方法
   * 无论promise状态是成功还是失败,回调函数始终会执行一次
   * 可以链式调用then方法
   * 使用 MyPromise.resolve 方法处理调用finally方法之后的返回值
   * @param {*} callback
   */
  finally(callback) {
    return this.then(
      (value) => {
        return MyPromise.resolve(callback()).then(() => value);
      },
      (reason) => {
        return MyPromise.resolve(callback()).then(() => {
          throw reason;
        });
      }
    );
  }

  /**
   * catch方法
   * 处理promise对象为失败的情况
   * @param {*} errorCallback
   */
  catch(errorCallback) {
    return this.then(null, errorCallback);
  }

  /**
   * Promise函数对象的all方法
   *
   * @param {*} array
   * @returns 返回一个promise对象,只有当所有promise都成功时返回的promise状态才成功
   */
  static all(array) {
    // 保存的结果
    let result = [];

    // 当前添加的数据的长度
    let _length = 0;
    return new MyPromise((resolve, reject) => {
      /**
       * 定义添加结果的方法
       * 当处理的数据和参数数组长度一致时说明处理完
       * 否则还有正在处理的promise
       * @param {*} index 添加的下标
       * @param {*} value 添加的值
       */
      function addResultItem(index, value) {
        result[index] = value;
        _length++;
        if (_length === array.length) {
          resolve(result);
        }
      }
      for (let i = 0; i < array.length; i++) {
        // 判断每一项的类型
        const current = array[i];
        if (current instanceof MyPromise) {
          // promise 对象
          current.then(
            (value) => addResultItem(i, value),
            (reason) => reject(reason)
          );
        } else {
          // 普通值
          addResultItem(i, current);
        }
      }
    });
  }

  /**
   * Promise函数对象的race方法
   * @param {*} array
   * @returns 返回一个promise对象,状态由第一个完成的promise决定
   */
  static race(array) {
    return new MyPromise((resolve, reject) => {
      for (let i = 0; i < array.length; i++) {
        const current = array[i];
        // 判断类型
        if (current instanceof MyPromise) {
          // promise 对象
          current.then(
            (value) => resolve(value),
            (reason) => reject(reason)
          );
        } else {
          // 普通值
          resolve(current);
        }
      }
    });
  }

  /**
   * Promise函数对象的resolve方法
   * @param {*} value
   * @returns 返回promise对象
   */
  static resolve(value) {
    /**
     * 判断value类型
     * 如果是promise对象 直接返回
     * 如果是普通值 返回新的promise
     */
    if (value instanceof MyPromise) return value;
    return new MyPromise((resolve) => resolve(value));
  }
}

/**
 * resolvePromise方法
 * 处理then方法的链式调用结果
 * @param {*} promise2 then方法返回的promise
 * @param {*} value then-成功的方法的返回值
 * @param {*} resolve MyPromise.resolve
 * @param {*} reject MyPromise.reject
 */
function resolvePromise(promise2, value, resolve, reject) {
  // 识别promise对象的自返回,不允许自己返回自己导致循环调用
  if (promise2 === value) {
    return reject(
      new TypeError("Chaining cycle detected for promise #<MyPromise>")
    );
  }
  if (value instanceof MyPromise) {
    // promise对象
    // value.then((value) => resolve(value), (reason) => reject(reason));
    value.then(resolve, reject);
  } else {
    // 普通值
    resolve(value);
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值