實現promise

// 三種狀態
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";
// promise 接收一個函數參數,該函數會當即執行
function MyPromise(fn) {
  let _this = this;
  _this.currentState = PENDING;
  _this.value = undefined;
  // 用於保存 then 中的回調,只有當 promise
  // 狀態爲 pending 時纔會緩存,而且每一個實例至多緩存一個
  _this.resolvedCallbacks = [];
  _this.rejectedCallbacks = [];

  _this.resolve = function (value) {
    if (value instanceof MyPromise) {
      // 若是 value 是個 Promise,遞歸執行
      return value.then(_this.resolve, _this.reject)
    }
    setTimeout(() => { // 異步執行,保證執行順序
      if (_this.currentState === PENDING) {
        _this.currentState = RESOLVED;
        _this.value = value;
        console.log(_this.resolvedCallbacks)
        _this.resolvedCallbacks.forEach(cb => cb());
      }
    })
  };

  _this.reject = function (reason) {
    setTimeout(() => { // 異步執行,保證執行順序
      if (_this.currentState === PENDING) {
        _this.currentState = REJECTED;
        _this.value = reason;
        _this.rejectedCallbacks.forEach(cb => cb());
      }
    })
  }
  // 用於解決如下問題
  // new Promise(() => throw Error('error))
  try {
    fn(_this.resolve, _this.reject);
  } catch (e) {
    _this.reject(e);
  }
}

MyPromise.prototype.then = function (onResolved, onRejected) {

  var self = this;
  // 規範 2.2.7,then 必須返回一個新的 promise
  var promise2;
  // 規範 2.2.onResolved 和 onRejected 都爲可選參數
  // 若是類型不是函數須要忽略,同時也實現了透傳
  // Promise.resolve(4).then().then((value) => console.log(value))
  onResolved = typeof onResolved === 'function' ? onResolved : v => v;
  onRejected = typeof onRejected === 'function' ? onRejected : v => v;
  if (self.currentState === RESOLVED) {
    return (promise2 = new MyPromise(function (resolve, reject) {
      // 規範 2.2.4,保證 onFulfilled,onRjected 異步執行
      // 因此用了 setTimeout 包裹下
      setTimeout(function () {
        try {
          var x = onResolved(self.value);
          resolutionProcedure(promise2, x, resolve, reject);
        } catch (reason) {
          reject(reason);
        }
      });
    }));
  }

  if (self.currentState === REJECTED) {
    return (promise2 = new MyPromise(function (resolve, reject) {
      setTimeout(function () {
        // 異步執行onRejected
        try {
          var x = onRejected(self.value);
          resolutionProcedure(promise2, x, resolve, reject);
        } catch (reason) {
          reject(reason);
        }
      });
    }));
  }

  if (self.currentState === PENDING) {
    return (promise2 = new MyPromise(function (resolve, reject) {
      self.resolvedCallbacks.push(function () {
        // 考慮到可能會有報錯,因此使用 try/catch 包裹
        try {
          var x = onResolved(self.value);
          resolutionProcedure(promise2, x, resolve, reject);
        } catch (r) {
          reject(r);
        }
      });

      self.rejectedCallbacks.push(function () {
        try {
          var x = onRejected(self.value);
          resolutionProcedure(promise2, x, resolve, reject);
        } catch (r) {
          reject(r);
        }
      });
    }));
  }
};
// 規範 2.3
function resolutionProcedure(promise2, x, resolve, reject) {
  // 規範 2.3.1,x 不能和 promise2 相同,避免循環引用
  if (promise2 === x) {
    return reject(new TypeError("Error"));
  }
  // 規範 2.3.2
  // 若是 x 爲 Promise,狀態爲 pending 須要繼續等待不然執行
  if (x instanceof MyPromise) {
    if (x.currentState === PENDING) {
      x.then(function (value) {
        // 再次調用該函數是爲了確認 x resolve 的
        // 參數是什麼類型,若是是基本類型就再次 resolve
        // 把值傳給下個 then
        resolutionProcedure(promise2, value, resolve, reject);
      }, reject);
    } else {
      x.then(resolve, reject);
    }
    return;
  }
  // 規範 2.3.3.3.3
  // reject 或者 resolve 其中一個執行過得話,忽略其餘的
  let called = false;
  // 規範 2.3.3,判斷 x 是否爲對象或者函數
  if (x !== null && (typeof x === "object" || typeof x === "function")) {
    // 規範 2.3.3.2,若是不能取出 then,就 reject
    try {
      // 規範 2.3.3.1
      let then = x.then;
      // 若是 then 是函數,調用 x.then
      if (typeof then === "function") {
        // 規範 2.3.3.3
        then.call(
          x,
          y => {
            if (called) return;
            called = true;
            // 規範 2.3.3.3.1
            resolutionProcedure(promise2, y, resolve, reject);
          },
          e => {
            if (called) return;
            called = true;
            reject(e);
          }
        );
      } else {
        // 規範 2.3.3.4
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    // 規範 2.3.4,x 爲基本類型
    resolve(x);
  }
}


複製代碼
相關文章
相關標籤/搜索