引出問題
不處理reject,瀏覽器會拋異常嗎?
考慮下列程式碼的執行情況
new Promise(function(resolve, reject) {
reject('reason')
})
複製程式碼
很多同學估計都會去Chrome的控制檯輸出一下,發現這段程式碼其實會往外拋一個異常
但是參考一個通過Promise/A+規範測試的Promise的原始碼,發現其reject並沒有往外丟擲異常
function reject(reason) {
if (self.status === 'pending') {
// 改變狀態
self.status = 'rejected'
// 保持值
self.data = reason
// 執行回撥
for(var i = 0; i < self.onRejectedCallback.length; i++) {
self.onRejectedCallback[i](reason)
}
}
}
複製程式碼
參考文章: 剖析Promise內部結構,一步一步實現一個完整的、能通過所有Test case的Promise類(目前大部按照PromiseA+規範實現Promise的文章,程式碼基本都是這樣的,其中這篇講解比較詳細,具有代表性)
查閱了一下PromiseA+的規範,其實並沒有規定reject要向外丟擲錯誤
各個引擎中的表現
-
Nodejs
Nodejs和Chrome一樣,也是基於v8的JS引擎。所以首先看看再Nodejs下的表現
-
Edge
沒拋異常,且IE看不到Promise的狀態
-
Firefox
為什麼
在promise-polyfill庫中找到了這樣的方法
大意就是,在reject裡面會執行Promise._unhandledRejectionFn
方法,由使用者自己決定怎麼處理這個reject的異常。顯然大多數瀏覽器原生Promise的選擇是,如果沒有catch進行處理,就丟擲
總結
- 其實,一般情況下,規範的使用catch就不會有上述問題了。在reject的情況下,只要後面有catch處理,就不會丟擲異常。沒有catch的情況下,一般會往外拋異常
- 在then的回撥函式中,如果出現了異常且後面沒有catch,還是會向外丟擲異常,所以合理使用catch是很重要的
- 最後,並不是說講解Promise實現的文章不好,而是PromiseA+沒有明確指出上述情況,所以希望讀者能夠了解到瀏覽器上的表現差異。