1.面試題
2.
目錄
- 常見 Promise 面試題
- Promise 出現的原因
- 什么是 Promise
- Promsie 與事件循環
- Promise 的升級
- 結語
Promise 出現的原因
在 Promise 出現以前,我們處理一個異步網絡請求,大概是這樣:
// 請求 代表 一個異步網絡調用。 // 請求結果 代表網絡請求的響應。 請求1(function(請求結果1){ 處理請求結果1 }) 復制代碼看起來還不錯。
但是,需求變化了,我們需要根據第一個網絡請求的結果,再去執行第二個網絡請求,代碼大概如下:請求1(function(請求結果1){ 請求2(function(請求結果2){ 處理請求結果2 }) }) 復制代碼看起來也不復雜。
但是。。需求是永無止境的,於是乎出現了如下的代碼:請求1(function(請求結果1){ 請求2(function(請求結果2){ 請求3(function(請求結果3){ 請求4(function(請求結果4){ 請求5(function(請求結果5){ 請求6(function(請求結果3){ ... }) }) }) }) }) }) 復制代碼這回傻眼了。。。 臭名昭著的 回調地獄 現身了。
更糟糕的是,我們基本上還要對每次請求的結果進行一些處理,代碼會更加臃腫,在一個團隊中,代碼 review 以及后續的維護將會是一個很痛苦的過程。
回調地獄帶來的負面作用有以下幾點:
- 代碼臃腫。
- 可讀性差。
- 耦合度過高,可維護性差。
- 代碼復用性差。
- 容易滋生 bug。
- 只能在回調里處理異常。
出現了問題,自然就會有人去想辦法。這時,就有人思考了,能不能用一種更加友好的代碼組織方式,解決異步嵌套的問題。
let 請求結果1 = 請求1(); let 請求結果2 = 請求2(請求結果1); let 請求結果3 = 請求3(請求結果2); let 請求結果4 = 請求2(請求結果3); let 請求結果5 = 請求3(請求結果4); 復制代碼類似上面這種同步的寫法。 於是 Promise 規范誕生了,並且在業界有了很多實現來解決回調地獄的痛點。比如業界著名的 Q 和 bluebird,bluebird 甚至號稱運行最快的類庫。
Promise的使用總結。
Promise 這么多概念,初學者很難一下子消化掉,那么我們可以采取強制記憶法,強迫自己去記住使用過程。
-
首先初始化一個 Promise 對象,可以通過兩種方式創建, 這兩種方式都會返回一個 Promise 對象。
- 1、new Promise(fn)
- 2、Promise.resolve(fn)
-
然后調用上一步返回的 promise 對象的 then 方法,注冊回調函數。
- then 中的回調函數可以有一個參數,也可以不帶參數。如果 then 中的回調函數依賴上一步的返回結果,那么要帶上參數。比如
new Promise(fn) .then(fn1(value){ //處理value }) 復制代碼 -
最后注冊 catch 異常處理函數,處理前面回調中可能拋出的異常。
通常按照這三個步驟,你就能夠應對絕大部分的異步處理場景。用熟之后,再去研究 Promise 各個函數更深層次的原理以及使用方式即可。
