模拟Promise模型

441 阅读2分钟

Promise 必须为以下三种状态之一:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。一旦Promise 被 resolve 或 reject,不能再迁移至其他任何状态(即状态 immutable)。

基本过程:

  1. 初始化 Promise 状态(pending)
  2. 立即执行 Promise 中传入的 fn 函数,将Promise 内部 resolve、reject 函数作为参数传递给 fn ,按事件机制时机处理
  3. 执行 then(..) 注册回调处理数组(then 方法可被同一个 promise 调用多次)
  4. Promise里的关键是要保证,then方法传入的参数 onFulfilled 和 onRejected,必须在then方法被调用的那一轮事件循环之后的新执行栈中执行。

真正的链式Promise是指在当前promise达到fulfilled状态后,即开始进行下一个promise.

用自定义的函数模拟出Promise的链式调用

new Promise((resolve, reject) => {
  resolve({ test: 1 });
})
  .then((data) => {
    console.log("result1", data);
    return "then后面的then";
  })
  .then((res) => {
    console.log(res);
  });
​
new Promise((resolve, reject) => {
  resolve({ test: 333 });
}).then((res) => {
  console.log(res);
});
//result1 { test: 1 }
//result3const l1 = new lszPromise((resolve, reject) => {
  resolve({ test: 1 });
})
  .then((data) => {
    console.log("lxm1", data);
    return "lszPromise then后面的then";
  })
  .then((res) => {
    console.log(res);
  });
​
new lszPromise((resolve, reject) => {
  resolve({ test: 333 });
}).then((res) => {
  console.log("lxm", res);
});
​
// 仿 promise函数
function lszPromise(fn) {
  let state = "pending"; // 状态标识, fulfilled, rejected
  let data = null;
  const callbackList = []; // 回调d对象队列
​
  fn(resolve, reject);
​
  function resolve(value) {
    // 因为是异步任务,所以需要使用setTimeout来模拟异步
    // 没有写异步函数,promise将是同步执行
    setTimeout(() => {
      if (state !== "pending") return; // 状态只能更改一次,所以改变之后不能执行
​
      state = "fulfilled";
      data = value;
      // 执行回调函数
      doCallBack();
    }, 0);
  }
​
  function reject(err) {
    setTimeout(() => {
      if (state !== "pending") return; // 状态只能更改一次,所以改变之后不能执行
​
      state = "rejected";
      data = err;
      // 执行回调函数
      doCallBack();
    }, 0);
  }
​
  function doCallBack() {
    // 执行回调队列中的函数
    while (callbackList.length) {
      // 获取队列首位
      const successFn = callbackList.shift();
      handle(successFn);
    }
  }
​
  // handle接收一个对象 onFulfilled回调函数, resolve函数
  function handle(callback) {
    if (state === "pending") {
      callbackList.push(callback);
      return;
    }
    if (state === "fulfilled") {
      if (!callback.onFulfilled) {
        callback.resolve(data);
        return;
      }
​
      const res = callback.onFulfilled(data);
      callback.resolve(res);
    }
  }
​
  this.then = function (onFulfilled) {
    return new lszPromise((resolve, reject) => {
      handle({
        onFulfilled,
        resolve,
      });
    });
  };
}
​

image-20211114231008033.png