前言
Promise 是一個很是簡單的概念,即便你沒有機會使用 Promise,你也可能閱讀過一些關於 Promise 的文章。
所謂 Promise,就是一個對象
,用來傳遞異步操做的消息。它表明了某個將來纔會知道結果的事件(一般是一個異步操做
),而且這個事件提供統一的 API,可供進一步處理。api
Promise的出現主要是解決地獄回調callback hell
的問題,好比你須要結果須要請求不少個接口,這些接口的參數須要另外那個的接口返回的數據做爲依賴,這樣就須要咱們一層嵌套一層,可是有了Promise 咱們就無需嵌套。數組
Promise 的價值在於使得異步代碼以一個更可讀的風格結構化,而不是因異步函數嵌套顯得混亂不堪。接下來接觸到 6 個你可能不知道的關於 Promise 的事。
開始列舉以前,先看看怎麼建立 Promise:
promise
先來看下面兩段代碼有什麼不一樣:異步
若是你認爲這兩段代碼是等價的那麼你可能會由於promise
僅僅就是一維回調函數的數組。然而這兩段代碼並不等價, 每次調用 then() 都會返回一個 forked promise
,所以,在A中若是func1中拋出異常,func2同樣會執行,在B中是promise 的鏈式寫法,操做的是func1中返回的
新的 promise`,因爲 func1 中拋出異常,這個 promise 被 rejected了,結果 func2 被跳過不執行了。函數
再來看下邊的代碼會 alert 什麼?
是否是誤覺得會alert出Hello world? 可是結果alert出來的確實undefined,緣由我上邊也提到了,在鏈式寫法上下文中,下一.then()
裏面操做的是上個返回來的新的promise
。 promise期待你的回調函數或者返回同一個結果,或者返回其餘結果可是會被傳給下一個回調。spa
再再看兩段代碼有什麼不同:
prototype
在A中,當第一個 then 拋出異常時,第二個 then 能捕獲到該異常,並會彈出 ''啊哦 拋出錯誤了''。這符合只捕獲來自上一級異常的規則。
在B中,正確的回調函數和錯誤的回調函數在同一級,也就是說,儘管在回調中拋出了異常,可是這個異常不會被捕獲。事實上,B中的錯誤回調只有在 promise 被 rejected 或者 promise 自身拋出一個異常時纔會被執行。3d
在一個錯誤毀掉中,若是沒有從新拋出錯誤,promise 會認爲你已經恢復了該錯誤,promise 的狀態,會從新轉變爲resolved
,在下面的栗子中會彈出 i am saved
, 是由於第一個then()中的錯誤回調函數被註釋了沒有從新拋出異常,換句話說下一級沒法捕獲到異常。
Promise 可被視爲洋蔥的皮層,每一次調用 then 都會被添加一層皮層,每個皮層表示一個能被處理的狀態,在皮層被處理以後,promise 會認爲已經修復了錯誤,並準備進入下一個皮層。code
僅僅由於你已經在一個 then() 函數中執行過代碼,並不意味着你不可以暫停 promise 去作其餘事情。爲了暫停當前的 promise,或者要它等待另外一個 promise 完成,只須要簡單地在 then() 函數中返回另外一個 promise。
在上面的代碼中,直到新的 promise 的狀態是 resolved解析後,alert 纔會顯示。若是要在已經存在的異步代碼中引入更多的依賴,這是一個很便利的方式。例如,你發現用戶會話已經超時了,所以,你可能想要在繼續執行後面的代碼以前發起第二次登陸。對象
再再再來看最後一個栗子, 運行下面代碼回彈出什麼呢???
第一眼看上去像不像2,由於 promise 已是 resolved ,then() 會當即執行(同步)。然而,promise規範要求是全部回調都是異步的,因此alert 執行時 i 的值尚未被修改,值依舊是0。