用原生js手寫實現promise

在足各上發表於2019-04-14

用原生js手寫實現promise,看了網上很多實現,最終寫出自己的簡易版promise,記錄一下

前言:使用及呼叫同原生Promise方法,只實現了then(resolve),catch(reject),finally()三個方法,不涉及Promise.race(),Promise.all();

  • 建構函式:

let that; // 儲存 mPromise
/**
 * 因為每次 new mPromise(then, catch的時候都需要鏈式呼叫)會呼叫 mPromise(constructor),
 * 所以放到外面
 */
// 狀態、引數配置
let config = {
  status: null,
  resolveParam: null,
  rejectParam: null
};

/**
 * mPromise函式:原生Promise的手動實現
 * @param {new mPromise時傳入的回撥函式} callback
 */
function mPromise(callback) {
  that = this;
  // 往new mPromise時傳入的回撥函式,傳回兩個引數
  callback(that.resolve, that.reject);
}
複製程式碼
  • 原型:

mPromise.prototype = {
  constructor: mPromise,
  resolve(param) {
    config.rejectParam = null; // 重置 reject 引數
    config.resolveParam = param;
    config.status = 'PENDING';
  },
  reject(param) {
    config.resolveParam = null; // 重置 resolve 引數
    config.rejectParam = param;
    config.status = 'PENDING';
  },
  then(_fn) {
    // 有resolve才呼叫
    if (config.resolveParam !== null) {
      config.status = 'RESOLVED';
      // 執行 then 的回撥,捕獲其中的報錯,呼叫 catch
      try {
        _fn(config.resolveParam);
      } catch (err) {
        config.rejectParam = err;
        that.catch(() => {});
      }
    }
    return new mPromise(() => {});
  },
  catch(_fn) {
    // 有reject才呼叫
    if (config.rejectParam !== null) {
      config.status = 'REJECTED';
      _fn(config.rejectParam);
    }
    return new mPromise(() => {});
  },
  finally(_fn) {
    // 初始化配置
    config = {
      status: null,
      resolveParam: null,
      rejectParam: null
    };
    _fn();
  }
};
複製程式碼
  • 使用方式同原生Promise:

let f1 = function(num) {
  return new mPromise((resolve, reject) => {
    if (num < 10) resolve(num);
    else if (num === 11) reject(num);
  });
};
複製程式碼
  • 然後呼叫:

f1(6)
  .then(res => {
    // cc; 開啟的話,會被 try catch捕獲,觸發catch,而不會往下走
    console.log('then: ', res); // then 6
  })
  .catch(err => {
    // 這裡會捕獲 then 裡面的報錯
    console.log('catch: ', err); // ReferenceError: cc is not defined
  });

f1(11)
  .then(res => {
    console.log('then: ', res);
  })
  .catch(err => {
    console.log('catch: ', err); // catch 11
  })
  .finally(() => {
    console.log('11 finally\n'); // 11 finally
  });

f1(12)
  .then(res => {
    console.log('then: ', res);
  })
  .catch(err => {
    console.log('catch: ', err);
  })
  .finally(() => {
    console.log('12 finally\n'); // 12 finally
  });
複製程式碼

結果:

then裡面不報錯:

圖片掛了...
then裡面有報錯:
圖片掛了...

到此,結束!

相關文章