你是否也在學習ES6 Promise時遇到過這個問題?

背景

週末閒來無事,隨便翻看了一下阮一峯老師的《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 入門》就夠了,好了,就到這裏吧,祝你們週末愉快!!

相關文章
相關標籤/搜索