手写Promise

66 阅读2分钟
//记录Promise的三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

/**
 * 运行一个微队列任务
 * 把传递的函数放到微队列中
 * @param {Function} callback
 */
function runMicroTask(callback) {
  //判断node环境
  if (process && process.nextTick) {
    process.nextTick(callback);
  }
  //浏览器环境--支持MutationObserver
  else if (MutationObserver) {
    const p = document.createElement("p");
    const observer = new MutationObserver(callback);
    observer.observe(p, {
      childList: true, //观察元素内部的变化,如果变化,则会将回调添加到微队列
    });
    p.innerHTML = "a"; //手动引起变化
  }
  //旧版本浏览器
  else {
    setTimeout(callback, 0); //直接添加到延时队列,凑活着用一下~
  }
}
/**
 * 判断一个数据是不是promise
 * @param {any} obj
 * @returns
 */
function isPromise(obj) {
  return !!(obj && typeof obj === "object" && typeof obj.then === "function");
}

class MyPromise {
  /**
   * 创建一个promise
   * @param {Function} executor 任务执行器, 立即执行
   */
  constructor(executor) {
    //初始化状态
    this.__status = PENDING;
    //初始化数据
    this.__value = undefined;
    //处理函数形成的队列
    this.__handlers = [];
    try {
      executor(this.__resolve.bind(this), this.__reject.bind(this));
    } catch (error) {
      //捕获运行期间的错误
      this.__reject(error);
    }
  }
  /**
   * 标记当前任务完成
   * @param {any} data 任务完成的相关数据
   */
  __resolve(data) {
    //改变状态和数据
    this.__changeState(FULFILLED, data);
  }
  /**
   * 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  __reject(reason) {
    //改变状态和数据
    this.__changeState(REJECTED, reason);
  }
  __changeState(newStatus, newValue) {
    if (this.__status !== PENDING) {
      //目前状态已经更改
      return;
    }
    this.__status = newStatus;
    this.__value = newValue;
    //状态变化,执行队列
    this.__runHandlers();
  }
  /**
   * Promise A+规范的then
   * @param {Function} onFulfilled
   * @param {Function} onRejected
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this.__pushHandlers(onFulfilled, FULFILLED, resolve, reject);
      this.__pushHandlers(onRejected, REJECTED, resolve, reject);
      this.__runHandlers(); //执行队列
    });
  }
  /**
   * 向处理队列中添加一个函数
   * @param {Function} executor 添加的函数
   * @param {String} status 该函数什么状态下执行
   * @param {Function} resolve 让then函数返回的promise成功
   * @param {Function} reject 让then函数返回的promise失败
   */
  __pushHandlers(executor, status, resolve, reject) {
    this.__handlers.push({
      executor,
      status,
      resolve,
      reject,
    });
  }
  /**
   * 根据实际情况,执行队列
   */
  __runHandlers() {
    if (this.__status === PENDING) {
      //挂起状态,不执行
      return;
    }
    //执行后删除
    while (this.__handlers[0]) {
      this.__runOneHandler(this.__handlers[0]);
      this.__handlers.shift();
    }
  }
  /**
   * 处理一个handler
   * @param {Function} handler
   */
  __runOneHandler({ executor, status, resolve, reject }) {
    runMicroTask(() => {
      //状态不一致,不执行
      if (status !== this.__status) return;
      //处理函数不是一个函数, 状态穿透(与之前保持一致)
      if (typeof executor !== "function") {
        this.__status === FULFILLED
          ? resolve(this.__value)
          : reject(this.__value);
      }
      try {
        const result = executor(this.__value);
        if (isPromise(result)) {
          result.then(resolve, reject);
        } else {
          resolve(result);
        }
      } catch (error) {
        reject(error);
      }
    });
  }
}