手写Promise

133 阅读2分钟
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

function runMicroTask(callback) {
  //判断当前执行环境
  if (process && process.nextTick) {
    //node环境,node环境下的nextTick属于微任务
    process.nextTick(callback);
  } else if (MutationObserver) {
    //浏览器环境
    const p = document.createElement("p");
    const observer = new MutationObserver(callback);
    observer.observe(p, {
      childList: true,
    });
    p.innerHTML = "1";
  } else {
    //其他环境,这里虽然不是最好的处理方法但却是最简单的处理方式
    setTimeout(callback, 0);
  }
}
function isPromise(obj) {
  //obj可能是0或者是undefined,该方法只需要返回true或false,因此需要'!!'做容错处理
  return !!(obj && typeof obj === "object" && typeof obj.then === "function");
}

class MyPromise {
  constructor(executor) {
    this._state = PENDING;
    this._value = undefined;
    this._handlers = [];
    //在es6的constructor里属于严格模式,this是undefined,需要通过bind改变this指向为promise实例对象
    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      this._reject(error);
    }
  }

  /**
   *
   * @param {Function} executor then方法添加的执行函数
   * @param {String} state  该函数在什么状态下执行
   * @param {Function} resolve  让then函数返回的promise成功
   * @param {Function} reject   让then函数返回的promise失败
   */
  _pushHandler(executor, state, resolve, reject) {
    this._handlers.push({
      executor,
      state,
      resolve,
      reject,
    });
  }

  then(onFulfilled, onRejected) {
    //then方法返回的也是一个promise
    return new MyPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandlers();
    });
  }

  //用于清空then方法所添加的执行队列,只有在promise改变状态时和执行then方法时执行
  _runHandlers() {
    if (this._state === PENDING) return;
    // console.log(`${this._handlers.length}个函数`);
    // console.log(this._handlers);
    //不要用for..of..循环或者for循环遍历数组然后使用shift方法清空数组第一位,会出现问题!
    while (this._handlers[0]) {
      //单个处理函数单个处理
      this._runOneHandler(this._handlers[0]);
      this._handlers.shift();
    }
  }

  _runOneHandler({ executor, state, resolve, reject }) {
    runMicroTask(() => {
      if (this._state !== state) return;
      //then方法中传入的是否为function
      if (typeof executor !== "function") {
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
      } else {
        try {
          const result = executor(this._value);
          if (isPromise(result)) {
            //如果then方法返回的是promise,那么then方法得到的结果就需要看该promise的状态是成功还是失败
            result.then(resolve, reject);
          } else {
            resolve(result);
          }
        } catch (error) {
          reject(error);
          console.error(error);
        }
      }
    });
  }

  //不希望用户直接调用以下三个方法
  _changeState(newState, newValue) {
    //状态只可以改变一次
    if (this._state != PENDING) return;
    this._state = newState;
    this._value = newValue;
    this._runHandlers();
  }
  _resolve(data) {
    this._changeState(FULFILLED, data);
  }
  _reject(reason) {
    this._changeState(REJECTED, reason);
  }
}