基础-promise的实现过程(4)

76 阅读6分钟

前面已经把所有的函数放到对列里了,里面有些函数会执行,有些不会执行,这得取决于状态。接下来去遍历这个对列,把函数拿出来,看看怎么处理。

  /**
   * @description: 根据实际情况 执行队列里
   * @return {*}
   */
  _runHandler() {
    if (this._state === PENDING) {
      // 任务仍在挂起
      return;
    }
  }

那状态改变了,需要看队列里的情况,所以状态一改变,就要执行队列。

  _changeState(state, value) {
    if (this._state !== PENDING) return;
    this._state = state;
    this._value = value;

    this._runHandler(); //状态改变 执行队列里的任务
  }

调用then的时候,向队列添加了函数,那这时也要看一下队列里函数的状态。

  then(onFulfilled, onRejected) {
    return new myPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandler(); //执行队列
    });
  }

ok,这时候,可以去处理队列了,当状态不是pending的时候,要执行相应的函数。


  /**
   * @description: 根据实际情况 执行队列里
   * @return {*}
   */
  _runHandler() {
    if (this._state === PENDING) {
      // 任务仍在挂起
      return;
    }
    for (const handler of this._handlers) {
      this._runOneHandler(handler);
    }
  }

  /**
   * @description: 处理队列里的每一个 对象
   * @param {Object} handler 队列里的对象
   * @return {*}
   */
  _runOneHandler(handler) {}

对了,处理完一个函数,要把它从队列里移除掉,不然如果后面再次调用then,那队列里的函数就会一直累加。

  _runHandler() {
    if (this._state === PENDING) {
      // 任务仍在挂起
      return;
    }
    for (const handler of this._handlers) {
      this._runOneHandler(handler);
      this._handlers.shift();//移除执行完的函数
    }
  }

嘿嘿,是不是就觉得访问了就删除,到最后就可以完全删除?nonono,不信你试试。

应该是while循环,才能搞定。

 _runHandler() {
    if (this._state === PENDING) {
      // 任务仍在挂起
      return;
    }
    while (this._handlers[0]) {
      const handler = this._handlers[0];
      this._runOneHandler(handler);
      this._handlers.shift(); //移除执行完的函数
    }
  }

ok,万事俱备,只欠东风。现在就来处理下这个runOneHandler执行器。

 /**
   * @description: 处理队列里的每一个 对象
   * @param {Object} handler 队列里的对象
   * @return {*}
   */
  _runOneHandler(handler) {}

现在把这个处理过程放到微队列里去执行。这个参数handler包含了then方法传递的函数和函数需要运行的状态,只有当myPromise的当前状态与队列里函数状态一致,才会执行该函数。

  _runOneHandler(handler) {
    runMicroTask(() => {
      if (this._state !== handler.state) {
        //状态不匹配
        return;
      };
    });
  }

还有一种情况,then没有传第二个参数,或者第二个参数不是一个函数。那这种要怎么处理?看下Promise的一个情况:

const p1 = p.then(function A1() {}) //第二个参数未传 则p1 的状态 和 p 的状态一致。
  _runOneHandler(handler) {
    runMicroTask(() => {
      if (this._state !== handler.state) {
        //状态不匹配
        return;
      }
      //第二个参数不是函数 则返回的promise状态和当前的状态一致
      if (typeof handler.excutor !== "function") {
        this._state === FULFILLED
          ? handler.resolve(this._value)
          : handler.reject(this._value);
          return;
      }
    });
  }

来看一下效果,我让myPromise1秒后失败,不传失败的处理函数,然后来看看当前myPromisethen返回的myPromise

const p = new myPromise((resolve, reject) => {
  setTimeout(() => {
    reject(1213);
  }, 1000);
});

const p1 = p.then(function A1() {});

setTimeout(() => {
  console.log("p", p);
  console.log("p1", p1);
}, 2000);

image.png 再来看看成功的情况。1秒后成功,不传成功的处理函数。

const p = new myPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
});

const p1 = p.then();

setTimeout(() => {
  console.log("p", p);
  console.log("p1", p1);
}, 2000);

image.png

现在两种特殊状态都处理了,那现在就来处理正常的结果。如果then传入的函数成功执行,那就执行resolve,如果出现错误了,那就执行reject

_runOneHandler({ excutor, state, resolve, reject }) {
    runMicroTask(() => {
      if (this._state !== state) {
        //状态不匹配
        return;
      }

      if (typeof excutor !== "function") {
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
        return;
      }

      // 根据`then`里面函数执行状态来 执行
      try {
        excutor(this._value);
      } catch (error) {
        reject(error);
      }
    });
  }

现在来看看then返回的myPromise状态。myPromise成功,执行then里的第一个函数(成功),执行期间抛出错误。

const p = new myPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  });
});

const p1 = p.then((value) => {
  throw "错误!"; //运行期间抛出错误
  return 1234;
});

setTimeout(() => {
  console.log("p1", p1);
}, 100);

image.png ok,被拒绝了,值为抛出的错误。

现在来处理then第一个函数运行没问题时的情况。

_runOneHandler({ excutor, state, resolve, reject }) {
    runMicroTask(() => {
      if (this._state !== state) {
        //状态不匹配
        return;
      }

      if (typeof excutor !== "function") {
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
        return;
      }

      try {
        const res = excutor(this._value);
        resolve(res); //保存成功的值
      } catch (error) {
        reject(error);
      }
    });
  }
  
  ...
  const p1 = p.then((value) => {
  return 1234;
});

image.png

ok了,能使用了。优化点小细节,如果then的参数返回的是一个myPromise,那怎么处理。

const p1 = p.then((value) => {
  return new myPromise((resolve, reject)=>{});
});

image.png 这种情况下,被圈住的这两个的状态和数据是一样的。那在_runOneHandler函数里又得处理一下这种情况。那怎么去判断是不是一个promise呢?其实不用符合ES6的,只要是满足了promise A+,那就是一个promise

/**
 * @description: 判断参数是不是一个 promise 对象 只要满足 Promise A+ 就是promise
 * @param {any} obj
 * @return {Boolean}
 */
function isPromise(obj) {
  return !!(obj && typeof obj === "object" && typeof obj.then === "function");
}
  _runOneHandler({ excutor, state, resolve, reject }) {
    runMicroTask(() => {
      if (this._state !== state) {
        //状态不匹配
        return;
      }

      if (typeof excutor !== "function") {
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
        return;
      }

      try {
        const res = excutor(this._value);
        if (isPromise(res)) {
          res.then(resolve, reject);
        } else {
          resolve(res);
        }
      } catch (error) {
        reject(error);
      }
    });
  }

到这里呢,就完成了整个Promise A+规范了,还是很曲折的,这就当做是笔记了,里面一堆的基础知识点和高阶函数,还要了解Promise的功能才能下手,着实有点难。下面是整个myPromise

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

/**
 * @description: 判断参数是不是一个 promise 对象 只要满足 Promise A+ 就是promise
 * @param {any} obj
 * @return {Boolean}
 */
function isPromise(obj) {
  return !!(obj && typeof obj === "object" && typeof obj.then === "function");
}

/**
 * @description:  运行一个微队列任务 or 把传递的函数放到微队列里
 * @param {Function} callback 函数
 * @return {*}
 */
function runMicroTask(callback) {
  // node environments
  // if (process && process.nextTick) {
  //   console.log("34", 34);
  //   process.nextTick(callback);
  // } else
  if (MutationObserver) {
    const a = document.createElement("span");
    new MutationObserver(callback).observe(a, {
      childList: true,
    });
    a.innerHTML = 1;
  } else {
    setTimeout(callback, 0);
  }
}

class myPromise {
  /**
   * @description: 构造函数
   * @param {Function} excutor 执行器,描述任务的执行过程 立即执行
   * @return {*}
   */
  constructor(excutor) {
    this._state = PENDING; //状态
    this._value = undefined; //数据
    this._handlers = []; //处理函数形成的队列

    try {
      excutor(this._resolve.bind(this), this._reject.bind(this)); //绑定this
    } catch (error) {
      this._reject(error);
    }
  }

  /**
   * @description: 向处理队列中添加一个函数,并标记类型
   * @param {Function} excutor 需要存入的函数
   * @param {String} state 该函数什么状态下执行
   * @param {Function} resolve 让then函数返回的 promise 成功
   * @param {Function} reject 让then函数返回的 promise 失败
   * @return {*}
   */
  _pushHandler(excutor, state, resolve, reject) {
    this._handlers.push({
      excutor,
      state,
      resolve,
      reject,
    });
  }

  /**
   * @description: 根据实际情况 执行队列里
   * @return {*}
   */
  _runHandler() {
    if (this._state === PENDING) {
      // 任务仍在挂起
      return;
    }
    while (this._handlers[0]) {
      const handler = this._handlers[0];
      this._runOneHandler(handler);
      this._handlers.shift(); //移除执行完的函数
    }
  }

  /**
   * @description: 处理队列里的每一个 对象
   * @param {Object} handler 队列里的对象
   * @return {*}
   */
  _runOneHandler({ excutor, state, resolve, reject }) {
    runMicroTask(() => {
      if (this._state !== state) {
        //状态不匹配
        return;
      }

      if (typeof excutor !== "function") {
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
        return;
      }

      try {
        const res = excutor(this._value);
        if (isPromise(res)) {
          res.then(resolve, reject);
        } else {
          resolve(res);
        }
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * @description: then 成功或失败要做的事 满足 Promise A+ 规范
   * @param {Function} onFulfilled 成功的回调
   * @param {Function} onRejected 失败的回调
   * @return {Object} Object 返回一个新的Promise
   */
  then(onFulfilled, onRejected) {
    return new myPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandler(); //执行队列
    });
  }

  /**
   * @description: 改变状态和数据
   * @param {String} state 状态
   * @param {any} value 数据
   * @return {*}
   */
  _changeState(state, value) {
    if (this._state !== PENDING) return;
    this._state = state;
    this._value = value;

    this._runHandler(); //状态改变 执行队列里的任务
  }

  /**
   * @description: 标记当前任务完成
   * @param {any} value 任务完成的相关数据
   */
  _resolve(value) {
    //改变状态和数据
    this._changeState(FULFILLED, value);
  }

  /**
   * @description: 标记当前任务失败
   * @param {any} reason 任务失败的相关数据
   */
  _reject(reason) {
    //改变状态和数据
    this._changeState(REJECTED, reason);
  }
}

export default myPromise;