週末閒來無事,隨便翻看了一下阮一峯老師的《ES6 標準入門》第2版,ps:以前在阮一峯老師的官網看過電子版,感受乾貨滿滿,因此就買了紙質版;當看到第16章第4節 'Promise.prototype.catch()'時,遇到了一個小困惑,下面咱們來一塊兒看一下es6
首先,Promise.prototype.catch方法是用來'捕獲Promise回調函數中天然發生或主動拋出的錯誤',何爲天然發生?何爲主動拋出?ajax
天然發生的錯誤:promise
1 function a() { 2 var x = 1; 3 console.log(x+y) 4 } 5 6 a() // 'ReferenceError: y is not defined'
變量y未定義,因此運行時產生了錯誤,這就是天然發生的錯誤,咱們沒有作異常處理,即try catch瀏覽器
主動拋出的錯誤:異步
1 function a() { 2 var x = 1; 3 try{ 4 console.log(x+y) 5 }catch(err){ 6 console.log(err) 7 } 8 } 9 10 a() // 'ReferenceError: y is not defined'
意識到可能會有異常出現,咱們就用try catch處理,那咱們如何區分一個錯誤是否被捕獲到了呢?很簡單,就是看瀏覽器控制檯的日誌:函數
未捕獲到的錯誤日誌是紅色的學習
捕獲到的錯誤日誌是黑色的this
上面已經說了Promise.prototype.catch的做用,以及錯誤的相關知識,那麼我究竟遇到了什麼問題呢?我們繼續往下看spa
書上有這麼一個示例:prototype
1 var promise = new Promise(function(resolve, reject){ 2 throw new Error('test') 3 }) 4 promise.catch(function(error){ 5 console.log(error) 6 }) 7 // Error: test
那咱們就手動實踐一下吧
錯誤真的被捕獲到了,歐耶,perfect!!忽然我又想到Promise不是用來實現異步操做的嗎?那咱們就試試ajax吧,而後又意識到沒有接口(主要是當時懶得找),那就用SetTimeout代替吧
代碼:
1 new Promise(function (resolve, reject) { 2 3 // 異步方式拋出異常 4 setTimeout(function () { 5 throw new Error('出錯1') 6 },2000) 7 8 // 同步方式拋出異常 9 throw new Error('出錯2') 10 }).catch(function (err) { 11 console.log(err) 12 })
運行截圖:
納尼?!錯誤1沒有被捕獲?開玩笑呢,讓我緩一緩,終於想到了:setTimeout是在Window下執行的,記得不?上面的代碼就至關於:
1 var clock = function () { 2 setTimeout(function () { 3 throw new Error('出錯1') 4 }) 5 } 6 7 new Promise(function (resolve, reject) { 8 9 // 異步方式拋出異常 10 clock() 11 12 // 同步方式拋出異常 13 throw new Error('出錯2') 14 }).catch(function (err) { 15 console.log(err) 16 })
當咱們執行一個函數時,歸根到底就是把函數體內代碼拿到它被調用的地方執行;因此在上上個示例中,在Promise實例中只是啓動了setTimeout定時器,以後定時器就和Promise實例徹底沒有關係了,由於它被交由Window對象了,因此定時器中拋出的異常沒有想咱們想象的被Promise示例捕獲,而是未加處理,直接在控制檯報錯;怎麼樣?你是否已經理解,若是理解了,咱們再鞏固一下,看看下面的代碼:
1 var clock = function () { 2 setTimeout(function () { 3 console.log(this === window) 4 throw new Error('出錯1') 5 }) 6 } 7 8 var func = function () { 9 throw new Error('出錯3') 10 } 11 12 13 new Promise(function (resolve, reject) { 14 // 異步方式拋出異常 15 clock() 16 17 // 執行window.func拋出異常 18 func() 19 20 // 同步方式拋出異常 21 throw new Error('出錯2') 22 }).catch(function (err) { 23 console.log(err) 24 })
這裏錯誤3能不能被catch捕獲呢?答案是:Yes
不要被迷惑呦!雖然func是在Promise示例外面定義的,可是它和錯誤2是拋出方式沒兩樣兒
這就是我在學習Promise相關知識時遇到的一個小插曲,我不相信只有我一我的有這個經歷,哈哈;關於Promise的其餘知識這裏不是沒有介紹,而是絲毫沒有介紹,很差意思,我又調皮了,主要是我以爲學習ES6,看阮一峯老師的《ECMAScript 6 入門》就夠了,好了,就到這裏吧,祝你們週末愉快!!