“我最近學習了Promise對象的使用,真是太棒了,使用鍊式調用代替了嵌套回調,代碼書寫起來很方便還便于閱讀” 小白說。
麥克黑:“是的,Promise是一種異步編程解決方案,尤其在多接口調用的時候會起到非常大的作用,方便開發” 。
小白撓撓頭說:“我閱讀了代碼知道了他的使用方式,我知道他有三種狀态:pending(進行中)、fulfilled(已成功)和rejected(已失敗),也能夠在項目中熟練使用,但我并不知道Promise内部的實現原理” 。
麥克黑:“如果你感興趣,我覺的你可以嘗試自己造輪子,來自己寫一個Promise對象,”
小白:“如果可以的話就太棒了,但是我應該如何着手寫一個自己的Promise對象呢?”
“當然可以,不過,以下談話價值兩杯咖啡外加一個雞肉卷”麥克黑狡黠的一笑。
“OK,成交了” 小白晃了晃手裡的星巴克優惠券。
今天我們來寫一個Promise對象一。在這之前要确保你完全明白如何使用他的各個方法。如果還不清楚那麼就去看下es6的文檔,不然下面的内容可能會看不明白
二。你完全了解發布/訂閱模式,這會然讓你對後面的代碼更容易理解,如果還不清楚就去看下我們上次的談話 《教你如何用ES6發布/訂閱模式約女朋友》”
“那麼首先你來寫一個最常用的Promise的使用方法”老麥克說到
“沒問題”
“寫的不錯,那麼我們就編寫一段代碼讓這段代碼能夠正常的運行”。
首先我們編寫一個Promise方法
在Promise方法裡我定義了 兩個數組 分别用來存放 成功時和失敗時要執行的函數,你還記得發布訂閱者模式嗎?
this.status 用來存放執行狀态。 this.value存放 返回的内容(不管成功與否)
接下來我們執行了 startResolve(this, fn); 方法。但現在我還不準備講解他的實現方式。
我們先實現then方法
當我們調用then方法的時候首先會判斷this.status的狀态
那麼我們首先看下addQueue方法。
addQueue方法的實現
你看到了嗎,開始push了,就像發布訂閱模式一樣。
resolve方法的實現
看下成功數組(resolves)裡有沒有函數,如果沒有直接返回false ,如果有函數我們就把失敗數組(rejects)的函數清除掉。修改status的狀态為 1,也就是resolve 解析成功然後調用resolves 列表裡的函數,也就是我們從then裡的函數push進來的函數。
reject方法的實現
和resolve是一個道理,你懂的,不解釋。
最後我們來看下startResolve都幹了些什麼。
startResolve() 方法的實現
看到了吧,延遲執行,在這裡我們用setTimeout來實現延遲在實際的es6的promise對象中他使用的是 asap模塊來實現的
var asap = require('asap/raw');
總結:也就是說我們先執行了then方法,把then裡的兩個匿名函數push到了promise的成功函數數組(resolves)和失敗函數數組裡(rejects),然後在執行pormise裡的函數等成功或者失敗以後再調用then裡提供的方法。懂了嗎?
最後我們來看下完整的Promise代碼實現。
到此我們的代碼編寫完畢,最開始的代碼還記得嗎?
在浏覽器中運行一下來驗證我們的代碼是否成功!
“完美運行,非常棒,難怪您會先讓我學習發布/訂閱模式,非常感謝”小白向老麥克豎起了大拇指。
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!