Promise 用es5的基礎實現

只實現 then 和 catchjavascript

function promise(fn) {
  var state = 'pending';
  // 聲明函數
  var nowResolve = function (arg) { return arg };
  var nowReject = function (arg) { return arg };
  var nextResolve = function (arg) { return arg };
  var nextReject = function (arg) { return arg };
  var catchReject = function (e) { throw e + ' (in promise)' };

  promise.prototype.then = function (res, rej) {
    typeof res === 'function' ? nowResolve = res : '';
    typeof rej === 'function' ? nowReject = rej : '';
    // return 新的對象
    return new promise(function (resolve, reject) {
      // then 中 return 的值傳遞給下一個 resolve/reject
      nextResolve = resolve;
      // 若是 then 中有 reject 回調函數, 則將 return 的值傳遞給下一個 resolve, 不然繼續傳遞給reject
      nextReject = typeof rej === 'function' ? resolve : reject;
      // 捕獲錯誤的回調函數
      catchReject = reject;
    });
  }

  promise.prototype.catch = function (fn) {
    return this.then(null, fn);
  }

  // 傳值到下一個回調,以及異常捕獲
  function tryCatchFn(state, arg) {
    try {
      state === 'fulfilled' ? nextResolve(nowResolve(arg)) : nextReject(nowReject(arg));
    } catch (e) {
      catchReject(e);
    }
  }

  function callback(value) {
    return function (arg) {
      if (state !== 'pending') { return; }
      state = value;
      // 若是傳參是 promise 構造器生成的對象,傳遞對象 resolve 的值
      if (arg instanceof promise) {
        arg.then(function (res) {
          tryCatchFn('fulfilled', res);
        }, function (rej) {
          tryCatchFn('rejected', rej);
        });
        return;
      }
      // 若是是普通的傳值,setTimeout 是爲了 resolve/reject 同步代碼的時候正常工做
      setTimeout(function () {
        tryCatchFn(state, arg);
      });
    }
  }

  fn(
    callback('fulfilled'),
    callback('rejected')
  );
}
相關文章
相關標籤/搜索