本文首發於 vivo互聯網技術 微信公眾號
鏈接: https://mp.weixin.qq.com/s/u8wuBwLpczkWCHx9TDt4Nw
作者:Morrain
Promise 是異步編程的一種解決方案,它由社區最早提出和實現,ES6 將其寫進了語言標准,統一了用法,原生提供了Promise對象。更多關於 Promise 的介紹請參考阮一峰老師的 ES6入門 之 Promise 對象。
很多同學在學習 Promise 時,知其然卻不知其所以然,對其中的用法理解不了。本系列文章由淺入深逐步實現 Promise,並結合流程圖、實例以及動畫進行演示,達到深刻理解 Promise 用法的目的。
本系列文章有如下幾個章節組成:
-
圖解 Promise 實現原理(三)—— Promise 原型方法實現
-
圖解 Promise 實現原理(四)—— Promise 靜態方法實現
一、【前言】
上一節中,實現了 Promise 的鏈式調用。鏈式調用是 Promise 的難點,更是重點。截至目前,Promise 的實現如下:
本節主要介紹 Promise 原型方法的實現,包括 catch、finally 以及 rejected 狀態等的實現。
二、【錯誤處理】
之前為了講解原理,只是實現了 onFulfilled ,對於 Promise 來說,除了成功還有失敗,在失敗時,要標記 Promise 的狀態為 rejected, 並執行注冊的 onRejected。如下Demo所示:
有了之前處理 fulfilled 狀態的經驗,支持錯誤處理變得很容易,只需要在注冊回調、處理狀態變更上都要加入新的 reject 邏輯。
運行結果如下:
三、【異常處理】
剛剛介紹了錯誤處理,是指在 Promise 的構造函數中發現的錯誤,並通過 reject 通知的。如果在執行 onFulfilled 或者 onRejected 時,出現了異常,該如何處理呢?對於這類異常,處理也很簡單,可以使用 try-catch 捕獲錯誤,然后將相應的 Promise 狀態設置為 rejected 狀態。改造_handle方法如下:
不管是錯誤也好,異常也罷,最終都是通過 reject 實現的,可見最終對於錯誤以及異常的處理,都可以通過 then 中的 onRejected 來處理。所以單獨增加一個 catch 方法,它是 .then(null, onRejected) 的別名。如下:
四、【Finally方法】
在實際應用的時候,我們很容易會碰到這樣的場景,不管 Promise 最后的狀態如何,都要執行某些操作(onDone)。例如服務器使用 Promise 處理請求,然后使用finally方法關掉服務器:
本質上,因為它是 then 的一種變形。上面的 demo 的效果等價於如下的代碼:
通過上面的分析,finally看上去可以這么實現:
但是由於 finally 方法的 onDone 不關心 Promise 的狀態到底是 fulfilled 還是 rejected ,所以onDone 里的操作,應該是與狀態無關的,並且不應該有任何參數。
如果使用 then 來實現就不符合 Promise 規范中關於《Why not .then(f, f)?》的說明 。一來 onDone 有參數,二來當 onDone 返回一個Promise時,會改變 finally 返回的Promise的值 狀態 。
根據規范,finally實現如下:
對於上面的示例,執行結果如下:
同樣可以通過示意動畫來還原這個過程:
finally 的實現看起來簡單,實際理解還是比較困難,對於上面的實例,中間其實有5個 Promise實例生成。如下圖所示:
原型方法就介紹這么多,下一節介紹兩個靜態方法
更多內容敬請關注 vivo 互聯網技術 微信公眾號
注:轉載文章請先與微信號:Labs2020 聯系。