一步一步實現一個符合PromiseA+規範的Promise庫(1)

今天咱們來本身手寫一個符合PromiseA+規範的Promise庫。你們是否是很激動呢??前端

clipboard.png

纔沒有。。
咱們都知道。在如今的前端開發中,Promise這個東西基本上全部的開發中都會用到。es6

那必然有些萌新就會問了,Promise究竟是個什麼東西呢。編程

按照規範來講。Promise是異步編程的一種解決方案,比傳統的解決方案——回調函數和事件——更合理和更強大。它由社區最先提出和實現,ES6 將其寫進了語言標準,統一了用法,原生提供了Promise對象。數組

通俗來說。。這個東西就是爲了解決咱們日常的回調函數,避免回調地獄的一種解決方案。因此說這個東西你們不只要會用哦,還應該知道他的一些原理。so,咱們一塊兒來實現下吧。異步

clipboard.png

接下來咱們先看一個簡單的Promise。異步編程

clipboard.png

這個就是es6標準中的Promise。咱們能夠看到,其實Promise就是一個構造函數。函數

這個構造函數中只有一個參數。這個參數在Promise/A+規範中被稱爲executor(執行者..我以爲叫執行器蠻好)。測試

由於這個執行器是爲了執行後面的resolve(決定)和reject(拒絕)方法。呃...其實你能夠把resolve看做是成功,把reject看作失敗。spa

固然了咱們還能夠根據本身定義的規則來進行Promise中resolve和reject的調用,不過這是用法,咱們這裏就當你們會用了。。對象

clipboard.png

而後咱們能夠看到,在構造函數的實例p中還有一個then方法。這裏咱們就要想了,既然是構造函數的實例上哪必然這個函數是掛在到這個構造函數的原型上。

還有很重要的一點就是咱們能夠想一下,在Promise中這個Promise的當前狀態是一個問題。在A+規範中規定:一個Promise只有三種狀態,咱們看圖

clipboard.png

什麼意思呢。。

大體的意思就是說,一個Promise有且僅有(pending->等待,fulfilled->已執行,rejected->已拒絕)這三種狀態中的一種(ps:我曾經看到過一個詞->懸而未決用來形容pending也不錯 :)。

咱們知道了這些,接下來咱們就來手動實現一個簡單的。

clipboard.png

繼續。。。。

clipboard.png

這裏咱們要說一下,貌似剛纔忘說了。。。

clipboard.png

咱們經過這張圖來看一下,當目前的狀態爲pending時。咱們能夠將pending狀態改變爲fulfilled或者rejected中的一種。然而咱們要記住,以前已經提到過Promise的狀態必須是三種之一。並且,若是一旦成功就不能失敗,一旦失敗就不能成功。

接下來咱們依據上面狀態的描述來繼續、、、

clipboard.png

這裏當咱們調用resolve和reject的時候咱們須要作出狀態判斷,只有是pending狀態的時候才能夠改變狀態爲其餘兩種的任意一種,若是不是:例如

clipboard.png

咱們處理完了resolve和reject內置的邏輯,這裏有一個問題。在開發中,當Promise的執行遇到錯誤時,會直接變成rejected狀態,你們應該都知道,也就是下面的處理。

clipboard.png

咱們在Promise的執行過程當中若是捕獲到異常,就能夠直接調用reject來結束Promise。

接下來咱們看then方法。

clipboard.png

這樣咱們就實現了一個簡單的Promise(纔沒有。。。這才哪到哪),咱們來試下效果吧。

clipboard.png

別忘了導出咱們的Promise。。

clipboard.png

clipboard.png

clipboard.png

咱們看到下面的輸出結果,哇!!好激動有沒有(纔沒有激動),我也實現了一個Promise!

可是!有一個問題,咱們是否是弄丟了一個狀態???

what??哪一個??仔細想一下好像是‘pending’丟掉了。。

so?那咋辦。

有人可能會說了,不是出了成功就是失敗嗎,爲何會有等待狀態呢,咱們來思考一下下面的代碼。

clipboard.png

話說Promise應該都是支持異步的吧?就像上面的代碼,異步執行resolve的時候咱們是否是已經吧值給弄丟了?

而且咱們想一下,弄丟這個值得一段時間是否是就是等待態也就是‘pending’的時候。。

因此,咱們要怎麼處理這個pending呢?

咱們想一下,在executor中的resolve和reject是否是都會吧咱們傳入的值,傳到then方法的onfulfilled和onrejected中?另外,咱們在then方法中作了對目前Promise的狀態的判斷。

因此咱們在then方法中去處理‘pending’狀態。

怎麼去處理呢?咱們能夠在Promise中掛載兩個數組。

clipboard.png

爲何?這兩個數組的做用是爲了記錄pending狀態下的onfulfilled和onreject函數。咱們來看then中的代碼。

clipboard.png

咱們能夠看到在pending狀態下,這兩個數組分別記錄了各自對應的then的回調函數,而且保存起來。

咱們來捋一捋思路。

clipboard.png

因此說咱們的數組裏存的是一個一個的then的回調函數,也就是一個一個function。

因此咱們要在resolve和reject方法觸發的時候,去便利咱們的數組而且執行其中的方法,而且呢還要把咱們成功的緣由(self.value)和失敗的緣由(self.reason)放到咱們的回調方法中去。說了這麼多有點繞。。上代碼

clipboard.png

這樣就解決了異步的問題。咱們再來測試一下。

代碼剛開始運行。

clipboard.png

2秒後。。。

clipboard.png

這時咱們就拿到了異步的值,是否是很開心!(有點,嘿嘿)

再看一下咱們寫的所有的代碼:

clipboard.png

到這裏咱們簡單瞭解了Promise的一小部分原理,而且實現了一個很是簡單的Promise。今天就先寫到這裏,在下一章中咱們會繼續瞭解Promise中的then方法是如何鏈式調用的,以及鏈式調用中的許多坑。。。

好啦,謝謝你們看到這裏。感謝。

clipboard.png

再次感謝。

相關文章
相關標籤/搜索