Promise 實現原理

在傳統的異步編程中,若是異步之間存在依賴關係,咱們就須要經過層層嵌套回調來知足這種依賴。javascript

若是嵌套層數過多,可讀性和可維護性都變得不好,產生所謂「回調地獄」,而Promise將回調嵌套改成鏈式調用,增長可讀性和可維護性。java

下面咱們就來一步步實現一個Promise。編程

觀察者模式

咱們先來看一個最簡單的Promise使用:設計模式

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('result')
    },
    1000);
}) 

p1.then(res => console.log(res), err => console.log(err))

觀察這個例子,咱們分析Promise的調用流程:promise

  • Promise的構造方法接收一個executor(),在new Promise()時就馬上執行這個executor回調
  • executor()內部的異步任務被放入宏/微任務隊列,等待執行
  • then()被執行,收集成功/失敗回調,放入成功/失敗隊列
  • executor()的異步任務被執行,觸發resolve/reject,從成功/失敗隊列中取出回調依次執行

其實熟悉設計模式的同窗,很容易就能意識到這是個觀察者模式,這種收集依賴 -> 觸發通知 -> 取出依賴執行 的方式,被普遍運用於觀察者模式的實現,在Promise裏,執行順序是then收集依賴 -> 異步觸發resolve -> resolve執行依賴。異步

依此,咱們能夠勾勒出Promise的大體形狀:異步編程

class MyPromise {
  // 構造方法接收一個回調
  constructor(executor) {
    this._resolveQueue = []    // then收集的執行成功的回調隊列
    this._rejectQueue = []     // then收集的執行失敗的回調隊列

    // 因爲resolve/reject是在executor內部被調用, 所以須要使用箭頭函數固定this指向, 不然找不到this._resolveQueue
    let _resolve = (val) => {
      // 從成功隊列裏取出回調依次執行
      while(this._resolveQueue.length) {
        const callback = this._resolveQueue.shift()
        callback(val)
      }
    }
    // 實現同resolve
    let _reject = (val) => {
      while(this._rejectQueue.length) {
        const callback = this._rejectQueue.shift()
        callback(val)
      }
    }
    // new Promise()時當即執行executor,並傳入resolve和reject
    executor(_resolve, _reject)
  }

  // then方法,接收一個成功的回調和一個失敗的回調,並push進對應隊列
  then(resolveFn, rejectFn) {
    this._resolveQueue.push(resolveFn)
    this._rejectQueue.push(rejectFn)
  }
}

寫完代碼咱們能夠測試一下:函數

const p1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve('result')
  }, 1000);
})
p1.then(res => console.log(res))
//一秒後輸出result

咱們運用觀察者模式簡單的實現了一下then和resolve,使咱們可以在then方法的回調裏取得異步操做的返回值,但咱們這個Promise離最終實現還有很長的距離,下面咱們來一步步補充這個Promise:學習

Promise A+規範

上面咱們已經簡單地實現了一個超低配版Promise,但咱們會看到不少文章和咱們寫的不同,他們的Promise實現中還引入了各類狀態控制,這是因爲ES6的Promise實現須要遵循Promise/A+規範,是規範對Promise的狀態控制作了要求。Promise/A+的規範比較長,這裏只總結兩條核心規則:測試

  • Promise本質是一個狀態機,且狀態只能爲如下三種:Pending(等待態)、Fulfilled(執行態)、Rejected(拒絕態),狀態的變動是單向的,只能從Pending -> Fulfilled 或 Pending -> Rejected,狀態變動不可逆
  • then方法接收兩個可選參數,分別對應狀態改變時觸發的回調。then方法返回一個promise。then 方法能夠被同一個 promise 調用屢次。

image.png

根據規範,咱們補充一下Promise的代碼:

//Promise/A+規範的三種狀態
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  // 構造方法接收一個回調
  constructor(executor) {
    this._status = PENDING     // Promise狀態
    this._resolveQueue = []    // 成功隊列, resolve時觸發
    this._rejectQueue = []     // 失敗隊列, reject時觸發

    // 因爲resolve/reject是在executor內部被調用, 所以須要使用箭頭函數固定this指向, 不然找不到this._resolveQueue
    let _resolve = (val) => {
      if(this._status !== PENDING) return   // 對應規範中的"狀態只能由pending到fulfilled或rejected"
      this._status = FULFILLED              // 變動狀態

      // 這裏之因此使用一個隊列來儲存回調,是爲了實現規範要求的 "then 方法能夠被同一個 promise 調用屢次"
      // 若是使用一個變量而非隊列來儲存回調,那麼即便屢次p1.then()也只會執行一次回調
      while(this._resolveQueue.length) {    
        const callback = this._resolveQueue.shift()
        callback(val)
      }
    }
    // 實現同resolve
    let _reject = (val) => {
      if(this._status !== PENDING) return   // 對應規範中的"狀態只能由pending到fulfilled或rejected"
      this._status = REJECTED               // 變動狀態
      while(this._rejectQueue.length) {
        const callback = this._rejectQueue.shift()
        callback(val)
      }
    }
    // new Promise()時當即執行executor,並傳入resolve和reject
    executor(_resolve, _reject)
  }

  // then方法,接收一個成功的回調和一個失敗的回調
  then(resolveFn, rejectFn) {
    this._resolveQueue.push(resolveFn)
    this._rejectQueue.push(rejectFn)
  }
}

then的鏈式調用

補充完規範,咱們接着來實現鏈式調用,這是Promise實現的重點和難點,咱們先來看一下then是如何鏈式調用的:

const p1 = new Promise((resolve, reject) => {
  resolve(1)
})

p1
  .then(res => {
    console.log(res)
    //then回調中能夠return一個Promise
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(2)
      }, 1000);
    })
  })
  .then(res => {
    console.log(res)
    //then回調中也能夠return一個值
    return 3
  })
  .then(res => {
    console.log(res)
  })

輸出

1
2
3

咱們思考一下如何實現這種鏈式調用:

  • 顯然.then()須要返回一個Promise,這樣才能找到then方法,因此咱們會把then方法的返回值包裝成Promise。
  • .then()的回調須要順序執行,以上面這段代碼爲例,雖然中間return了一個Promise,但執行順序仍要保證是1->2->3。咱們要等待當前Promise狀態變動後,再執行下一個then收集的回調,這就要求咱們對then的返回值分類討論
// then方法
then(resolveFn, rejectFn) {
  //return一個新的promise
  return new MyPromise((resolve, reject) => {
    //把resolveFn從新包裝一下,再push進resolve執行隊列,這是爲了可以獲取回調的返回值進行分類討論
    const fulfilledFn = value => {
      try {
        //執行第一個(當前的)Promise的成功回調,並獲取返回值
        let x = resolveFn(value)
        /**
         * 分類討論返回值,若是是Promise,那麼等待Promise狀態變動,不然直接resolve
         *
         *     這裏是難點,若是 回調函數的返回值 x 是一個promise,則咱們須要經過 x.then再
         *  註冊一個(兩個)回調,目的是爲了保證只有當 x 這個promise 的狀態改變之後
         * (promise 就緒)才執行後續的回調(即後面 then 註冊的回調);若是 x 不是
         *  promise,則直接執行 resolve(x), 好比 resolve(number) 或者 
         *  resolve(undefined)
         *
         *  這裏若是讀者理解困難,必定要本身敲一遍,執行一遍示例 + console.log打日誌,基本
         *  上就能理解了
         */
        x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
      } catch (error) {
        reject(error)
      }
    }
    //把後續then收集的依賴都push進當前Promise的成功回調隊列中(_rejectQueue), 這是爲了保證順序調用,理解這句對於理解 then 的順序執行以及 _resolve 函數中回調隊列的執行很重要
    this._resolveQueue.push(fulfilledFn)

    //reject同理
    const rejectedFn  = error => {
      try {
        let x = rejectFn(error)
        x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
      } catch (error) {
        reject(error)
      }
    }
    this._rejectQueue.push(rejectedFn)
  })
}

而後咱們就能測試一下鏈式調用:

const p1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 500);
})

p1
  .then(res => {
    console.log(res)
    return 2
  })
  .then(res => {
    console.log(res)
    return 3
  })
  .then(res => {
    console.log(res)
  })

//輸出 1 2 3

值穿透 & 狀態已變動的狀況

咱們已經初步完成了鏈式調用,可是對於 then() 方法,咱們還要兩個細節須要處理一下

  • 值穿透

    根據規範,若是 then() 接收的參數不是function,那麼咱們應該忽略它。若是沒有忽略,當then()回調不爲function時將會拋出異常,致使鏈式調用中斷

  • 處理狀態爲resolve/reject的狀況

    其實咱們上邊 then() 的寫法是對應狀態爲pending的狀況,可是有些時候,resolve/reject 在 then() 以前就被執行(好比Promise.resolve().then()),若是這個時候還把then()回調push進resolve/reject的執行隊列裏,那麼回調將不會被執行,所以對於狀態已經變爲fulfilled或rejected的狀況,咱們直接執行then回調:

// then方法,接收一個成功的回調和一個失敗的回調
then(resolveFn, rejectFn) {
  // 根據規範,若是then的參數不是function,則咱們須要忽略它, 讓鏈式調用繼續往下執行(經過從新定義這兩個函數來實現該目的)
  typeof resolveFn !== 'function' ? resolveFn = value => value : null
  typeof rejectFn !== 'function' ? rejectFn = reason => {
    throw new Error(reason instanceof Error? reason.message:reason);
  } : null
  
  // return一個新的promise
  return new MyPromise((resolve, reject) => {
    // 把resolveFn從新包裝一下,再push進resolve執行隊列,這是爲了可以獲取回調的返回值進行分類討論
    const fulfilledFn = value => {
      try {
        // 執行第一個(當前的)Promise的成功回調,並獲取返回值
        let x = resolveFn(value)
        // 分類討論返回值,若是是Promise,那麼等待Promise狀態變動,不然直接resolve
        x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
      } catch (error) {
        reject(error)
      }
    }
  
    // reject同理
    const rejectedFn  = error => {
      try {
        let x = rejectFn(error)
        x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
      } catch (error) {
        reject(error)
      }
    }
  
    switch (this._status) {
      // 當狀態爲pending時,把then回調push進resolve/reject執行隊列,等待執行
      case PENDING:
        this._resolveQueue.push(fulfilledFn)
        this._rejectQueue.push(rejectedFn)
        break;
      // 當狀態已經變爲resolve/reject時,直接執行then回調
      case FULFILLED:
        fulfilledFn(this._value)    // this._value是上一個then回調return的值(見完整版代碼)
        break;
      case REJECTED:
        rejectedFn(this._value)
        break;
    }
  })
}

兼容同步任務

完成了then的鏈式調用之後,咱們再處理一個前邊的細節,而後放出完整代碼。

上文咱們說過,Promise的執行順序是new Promise -> then()收集回調 -> resolve/reject執行回調,這一順序是創建在executor是異步任務的前提上的。

若是executor是一個同步任務,那麼順序就會變成new Promise -> resolve/reject執行回調 -> then()收集回調,resolve的執行跑到then以前去了,爲了兼容這種狀況,咱們給resolve/reject執行回調的操做包一個setTimeout,讓它異步執行。

提示

這裏插一句,有關這個setTimeout,其實還有一番學問。雖然規範沒有要求回調應該被放進宏任務隊列仍是微任務隊列,但其實Promise的默認實現是放進了微任務隊列,咱們的實現(包括大多數Promise手動實現和polyfill的轉化)都是使用setTimeout放入了宏任務隊列(固然咱們也能夠用MutationObserver模擬微任務)

//Promise/A+規定的三種狀態
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  // 構造方法接收一個回調
  constructor(executor) {
    this._status = PENDING     // Promise狀態
    this._value = undefined    // 儲存then回調return的值
    this._resolveQueue = []    // 成功隊列, resolve時觸發
    this._rejectQueue = []     // 失敗隊列, reject時觸發

    // 因爲resolve/reject是在executor內部被調用, 所以須要使用箭頭函數固定this指向, 不然找不到this._resolveQueue
    let _resolve = (val) => {
      //把resolve執行回調的操做封裝成一個函數,放進setTimeout裏,以兼容executor是同步代碼的狀況
      const run = () => {
        if(this._status !== PENDING) return   // 對應規範中的"狀態只能由pending到fulfilled或rejected"
        this._status = FULFILLED              // 變動狀態
        this._value = val                     // 儲存當前value

        // 這裏之因此使用一個隊列來儲存回調,是爲了實現規範要求的 "then 方法能夠被同一個 promise 調用屢次"
        // 若是使用一個變量而非隊列來儲存回調,那麼即便屢次p1.then()也只會執行一次回調
        while(this._resolveQueue.length) {    
          const callback = this._resolveQueue.shift()
          callback(val)
        }
      }
      setTimeout(run)
    }
    // 實現同resolve
    let _reject = (val) => {
      const run = () => {
        if(this._status !== PENDING) return   // 對應規範中的"狀態只能由pending到fulfilled或rejected"
        this._status = REJECTED               // 變動狀態
        this._value = val                     // 儲存當前value
        while(this._rejectQueue.length) {
          const callback = this._rejectQueue.shift()
          callback(val)
        }
      }
      setTimeout(run)
    }
    // new Promise()時當即執行executor,並傳入resolve和reject
    executor(_resolve, _reject)
  }

  // then方法,接收一個成功的回調和一個失敗的回調
  then(resolveFn, rejectFn) {
    // 根據規範,若是then的參數不是function,則咱們須要忽略它, 讓鏈式調用繼續往下執行
    typeof resolveFn !== 'function' ? resolveFn = value => value : null
    typeof rejectFn !== 'function' ? rejectFn = reason => {
      throw new Error(reason instanceof Error? reason.message:reason);
    } : null
  
    // return一個新的promise
    return new MyPromise((resolve, reject) => {
      // 把resolveFn從新包裝一下,再push進resolve執行隊列,這是爲了可以獲取回調的返回值進行分類討論
      const fulfilledFn = value => {
        try {
          // 執行第一個(當前的)Promise的成功回調,並獲取返回值
          let x = resolveFn(value)
          // 分類討論返回值,若是是Promise,那麼等待Promise狀態變動,不然直接resolve
          x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
        } catch (error) {
          reject(error)
        }
      }
  
      // reject同理
      const rejectedFn  = error => {
        try {
          let x = rejectFn(error)
          x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
        } catch (error) {
          reject(error)
        }
      }
  
      switch (this._status) {
        // 當狀態爲pending時,把then回調push進resolve/reject執行隊列,等待執行
        case PENDING:
          this._resolveQueue.push(fulfilledFn)
          this._rejectQueue.push(rejectedFn)
          break;
        // 當狀態已經變爲resolve/reject時,直接執行then回調
        case FULFILLED:
          fulfilledFn(this._value)    // this._value是上一個then回調return的值(見完整版代碼)
          break;
        case REJECTED:
          rejectedFn(this._value)
          break;
      }
    })
  }
}

而後咱們能夠測試一下這個Promise:

const p1 = new MyPromise((resolve, reject) => {
  resolve(1)          //同步executor測試
})

p1
  .then(res => {
    console.log(res)
    return 2          //鏈式調用測試
  })
  .then()             //值穿透測試
  .then(res => {
    console.log(res)
    return new MyPromise((resolve, reject) => {
      resolve(3)      //返回Promise測試
    })
  })
  .then(res => {
    console.log(res)
    throw new Error('reject測試')   //reject測試
  })
  .then(() => {}, err => {
    console.log(err)
  })

// 輸出 
// 1 
// 2 
// 3 
// Error: reject測試

到這裏,咱們已經實現了Promise的主要功能(`∀´)Ψ剩下的幾個方法都很是簡單,咱們順手收拾掉:

  • Promise.prototype.catch()

catch()方法返回一個Promise,而且處理拒絕的狀況。它的行爲與調用Promise.prototype.then(undefined, onRejected) 相同。

//catch方法其實就是執行一下then的第二個回調
catch (rejectFn) {
  return this.then(undefined, rejectFn)
}
  • Promise.prototype.finally()

finally()方法返回一個Promise。在promise結束時,不管結果是fulfilled或者是rejected,都會執行指定的回調函數。在finally以後,還能夠繼續then。而且會將值原封不動的傳遞給後面的then

//finally方法
finally(callback) {
  return this.then(
    // MyPromise.resolve執行回調,並在then中return結果傳遞給後面的Promise
    value => MyPromise.resolve(callback()).then(() => value),
    // reject同理
    reason => MyPromise.resolve(callback()).then(() => { throw reason })  
  )
}
  • Promise.resolve()

Promise.resolve(value)方法返回一個以給定值解析後的Promise 對象。若是該值爲promise,返回這個promise;若是這個值是thenable(即帶有"then" 方法)),返回的promise會「跟隨」這個thenable的對象,採用它的最終狀態;不然返回的promise將以此值完成。此函數將類promise對象的多層嵌套展平。

//靜態的resolve方法
static resolve(value) {
  if(value instanceof MyPromise) return value // 根據規範, 若是參數是Promise實例, 直接return這個實例
  return new MyPromise(resolve => resolve(value))
}
  • Promise.reject()

Promise.reject()方法返回一個帶有拒絕緣由的Promise對象。

//靜態的reject方法
static reject(reason) {
  return new MyPromise((resolve, reject) => reject(reason))
}
  • Promise.all()

Promise.all(iterable)方法返回一個 Promise 實例,此實例在 iterable 參數內全部的 promise 都「完成(resolved)」或參數中不包含 promise 時回調完成(resolve);若是參數中  promise 有一個失敗(rejected),此實例回調失敗(reject),失敗緣由的是第一個失敗 promise 的結果。

//靜態的all方法
static all(promiseArr) {
  let index = 0
  let result = []
  return new MyPromise((resolve, reject) => {
    promiseArr.forEach((p, i) => {
      //Promise.resolve(p)用於處理傳入值不爲Promise的狀況
      MyPromise.resolve(p).then(
        val => {
          index++
          result[i] = val
          //全部then執行後, resolve結果
          if(index === promiseArr.length) {
            resolve(result)
          }
        },
        err => {
          //有一個Promise被reject時,MyPromise的狀態變爲reject
          reject(err)
        }
      )
    })
  })
}
  • Promise.race()

Promise.race(iterable)方法返回一個 promise,一旦迭代器中的某個promise解決或拒絕,返回的 promise就會解決或拒絕。

static race(promiseArr) {
  return new MyPromise((resolve, reject) => {
    //同時執行Promise,若是有一個Promise的狀態發生改變,就變動新MyPromise的狀態
    for (let p of promiseArr) {
      MyPromise.resolve(p).then(  //Promise.resolve(p)用於處理傳入值不爲Promise的狀況
        value => {
          resolve(value)        //注意這個resolve是上邊new MyPromise的
        },
        err => {
          reject(err)
        }
      )
    }
  })
}
  • 完整代碼
//Promise/A+規定的三種狀態
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
  // 構造方法接收一個回調
  constructor(executor) {
    this._status = PENDING     // Promise狀態
    this._value = undefined    // 儲存then回調return的值
    this._resolveQueue = []    // 成功隊列, resolve時觸發
    this._rejectQueue = []     // 失敗隊列, reject時觸發

    // 因爲resolve/reject是在executor內部被調用, 所以須要使用箭頭函數固定this指向, 不然找不到this._resolveQueue
    let _resolve = (val) => {
      //把resolve執行回調的操做封裝成一個函數,放進setTimeout裏,以兼容executor是同步代碼的狀況
      const run = () => {
        if(this._status !== PENDING) return   // 對應規範中的"狀態只能由pending到fulfilled或rejected"
        this._status = FULFILLED              // 變動狀態
        this._value = val                     // 儲存當前value

        // 這裏之因此使用一個隊列來儲存回調,是爲了實現規範要求的 "then 方法能夠被同一個 promise 調用屢次"
        // 若是使用一個變量而非隊列來儲存回調,那麼即便屢次p1.then()也只會執行一次回調
        while(this._resolveQueue.length) {    
          const callback = this._resolveQueue.shift()
          callback(val)
        }
      }
      setTimeout(run)
    }
    // 實現同resolve
    let _reject = (val) => {
      const run = () => {
        if(this._status !== PENDING) return   // 對應規範中的"狀態只能由pending到fulfilled或rejected"
        this._status = REJECTED               // 變動狀態
        this._value = val                     // 儲存當前value
        while(this._rejectQueue.length) {
          const callback = this._rejectQueue.shift()
          callback(val)
        }
      }
      setTimeout(run)
    }
    // new Promise()時當即執行executor,並傳入resolve和reject
    executor(_resolve, _reject)
  }

  // then方法,接收一個成功的回調和一個失敗的回調
  then(resolveFn, rejectFn) {
    // 根據規範,若是then的參數不是function,則咱們須要忽略它, 讓鏈式調用繼續往下執行
    typeof resolveFn !== 'function' ? resolveFn = value => value : null
    typeof rejectFn !== 'function' ? rejectFn = reason => {
      throw new Error(reason instanceof Error? reason.message:reason);
    } : null
  
    // return一個新的promise
    return new MyPromise((resolve, reject) => {
      // 把resolveFn從新包裝一下,再push進resolve執行隊列,這是爲了可以獲取回調的返回值進行分類討論
      const fulfilledFn = value => {
        try {
          // 執行第一個(當前的)Promise的成功回調,並獲取返回值
          let x = resolveFn(value)
          // 分類討論返回值,若是是Promise,那麼等待Promise狀態變動,不然直接resolve
          x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
        } catch (error) {
          reject(error)
        }
      }
  
      // reject同理
      const rejectedFn  = error => {
        try {
          let x = rejectFn(error)
          x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
        } catch (error) {
          reject(error)
        }
      }
  
      switch (this._status) {
        // 當狀態爲pending時,把then回調push進resolve/reject執行隊列,等待執行
        case PENDING:
          this._resolveQueue.push(fulfilledFn)
          this._rejectQueue.push(rejectedFn)
          break;
        // 當狀態已經變爲resolve/reject時,直接執行then回調
        case FULFILLED:
          fulfilledFn(this._value)    // this._value是上一個then回調return的值(見完整版代碼)
          break;
        case REJECTED:
          rejectedFn(this._value)
          break;
      }
    })
  }

  //catch方法其實就是執行一下then的第二個回調
  catch(rejectFn) {
    return this.then(undefined, rejectFn)
  }

  //finally方法
  finally(callback) {
    return this.then(
      value => MyPromise.resolve(callback()).then(() => value),             //執行回調,並returnvalue傳遞給後面的then
      reason => MyPromise.resolve(callback()).then(() => { throw reason })  //reject同理
    )
  }

  //靜態的resolve方法
  static resolve(value) {
    if(value instanceof MyPromise) return value //根據規範, 若是參數是Promise實例, 直接return這個實例
    return new MyPromise(resolve => resolve(value))
  }

  //靜態的reject方法
  static reject(reason) {
    return new MyPromise((resolve, reject) => reject(reason))
  }

  //靜態的all方法
  static all(promiseArr) {
    let index = 0
    let result = []
    return new MyPromise((resolve, reject) => {
      promiseArr.forEach((p, i) => {
        //Promise.resolve(p)用於處理傳入值不爲Promise的狀況
        MyPromise.resolve(p).then(
          val => {
            index++
            result[i] = val
            if(index === promiseArr.length) {
              resolve(result)
            }
          },
          err => {
            reject(err)
          }
        )
      })
    })
  }

  //靜態的race方法
  static race(promiseArr) {
    return new MyPromise((resolve, reject) => {
      //同時執行Promise,若是有一個Promise的狀態發生改變,就變動新MyPromise的狀態
      for (let p of promiseArr) {
        MyPromise.resolve(p).then(  //Promise.resolve(p)用於處理傳入值不爲Promise的狀況
          value => {
            resolve(value)        //注意這個resolve是上邊new MyPromise的
          },
          err => {
            reject(err)
          }
        )
      }
    })
  }
}

結尾

咱們從一個最簡單的Promise使用實例開始,經過對調用流程的分析,根據觀察者模式實現了Promise的大體骨架,而後依據Promise/A+規範填充代碼,重點實現了then 的鏈式調用,最後完成了Promise的靜態/實例方法。

其實Promise實如今總體上並無太複雜的思想,但咱們平常使用的時候每每忽略了不少Promise細節,於是很難寫出一個符合規範的Promise實現,源碼的實現過程,其實也是對Promise使用細節從新學習的過程。

相關文章
相關標籤/搜索