手動實現Promise

weixin_33763244發表於2017-07-19

基本原理

今天心血來潮,哈哈,就想寫個promise物件,需要說的是,我沒有參考誰的程式碼,也沒有去看promise的原始碼,當然,我實現的是一個乞丐版的promise,只有then & catch 的功能,其中catch只能抓取一次。僅供大夥閒暇看看,打發下時間。程式碼註釋簡單說了下,如下:

import _ from 'lodash'

var compose = _.flowRight

class Xpromise {
  constructor(f) {
    this._value = f.bind(undefined, this.resolve, this.reject) // 為傳入的 函式 繫結resolve & reject 方法
    this.chain = undefined // 把then傳入的方法 通過compose 處理成鏈式呼叫
    this.errFunc = [] // 把catch 傳入的方法
    setTimeout( () => { // 如果new 一個新的物件,傳入的函式不是非同步的,則chain & errFunc 拿不到就執行了。所以使用定時器延時執行。
      this.errHandle(this._value)()
    }, 0)
    this.status = 'pending' // 設定Xpromise 狀態 主要作用是 確保resolve & reject只能執行其中一個
    return this
  }
  resolve = (data) => {
    if(this.status == 'pending')
      this.status = 'resolved'
    this.status == 'resolved' && this.chain && this.chain(data)
  }
  reject = (data) => {
    if(this.status == 'pending')
      this.status = 'rejected'

    this.status = 'rejected' && this.errFunc[0](data)
  }
  then = (f) => {
    this.chain = this.chain? compose(this.errHandle(f), this.chain): this.errHandle(f)
    return this
  }
  errHandle = (f) => {// 為每個傳入的函式包裹 錯誤檢查 程式碼
    return function() {
      var args = Array.prototype.slice.call(arguments, 0)
      try{
        return f.apply(f,args)
      }catch(e){
        if(this.errFunc.length !== 0)
          this.errFunc[0](e)
        else
          throw new Error(e)

        return
      }
    }
  }
  catch = (f) => {
    this.errFunc.push(f)
    return this
  }
}

相關文章