promise實例的catch方法


Promise.prototype.catch()

Promise.prototype.catch()方法是用於指定發生錯誤時的回調函數

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 處理 getJSON 和 前一個回調函數運行時發生的錯誤
  console.log('發生錯誤!', error);
});

      上邊代碼中,getJSON( )方法返回一個Promise對象,如果該對象狀態為resolved,則會調用then()方法指定的回調函數;如果異步操作拋出錯誤,狀態就會變為rejected,就會調用catch( )方法指定的回調函數,處理這個錯誤。另外,then( )方法指定的回調函數,如果運行中拋出錯誤,也會被catch( )方法捕獲。

p.then((val) => console.log('fulfilled:', val))
  .catch((err) => console.log('rejected', err));
// 等同於
p.then((val) => console.log('fulfilled:', val))
  .then(null, (err) => console.log("rejected:", err));

 

下面是一個例子

const promise = new Promise(function(resolve, reject) {
  throw new Error('test');
});
promise.catch(function(error) {
  console.log(error);
});
// Error: test

       上邊代碼中,promise拋出一個錯誤,就被catch方法指定的回調函數捕獲。

 

Promise對象的錯誤具有冒泡的性質,會一直向后傳遞,直到被捕獲為止。

getJSON('/post/1.json').then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // some code
}).catch(function(error) {
  // 處理前面三個Promise產生的錯誤
});

         上邊的代碼中,一共有三個Promise對象:一個由getJSON( )產生,兩個由then( )產生。它們中,任何一個拋出錯誤,都會被最后一個catch( )捕獲。

 

一般來說,不在then()方法里面定義Reject狀態的回調函數(即then的第二個參數),總是使用catch方法。

// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

         上邊的代碼,第二種寫法優於第一種,理由是第二種寫法可以捕獲前面then方法執行中的錯誤。因此,建議總是使用catch()方法,而不是使用then( )方法的第二個參數。

 

與傳統的try/catch代碼塊不同的是,如果沒有使用catch()方法指定錯誤處理的回調函數,Promise對象拋出的錯誤不會傳遞到外層代碼,即不會有任何反應,

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行會報錯,因為x沒有聲明
    resolve(x + 2);
  });
};

someAsyncThing().then(function() {
  console.log('everything is great');
});

setTimeout(() => { console.log(123) }, 2000);
// Uncaught (in promise) ReferenceError: x is not defined
// 123

      上邊的代碼中,someAsyncThing( )函數產生的Promise對象,內部有語法錯誤,瀏覽器運行到這一行,會打印出錯誤提示,但是不會退出進程,終止腳本運行,2s之后還是會輸出123。 這就是說,Promise內部的錯誤不會影響到Promise外部的代碼,通俗的說法就是“Promise 會吃掉錯誤

 

這個腳本放在服務器執行,退出碼是0(即表示執行成功)。不過,Node.js有一個unhandleRejection事件,專門監聽未捕獲的reject錯誤,上邊的腳本會觸發這個事件的監聽函數,可以在監聽函數里面拋出錯誤。

process.on('unhandledRejection', function (err, p) {
  throw err;
});

      上邊的代碼中,unhandleRejection事件的監聽函數有兩個參數,第一個是錯誤對象,第二個是報錯的Promise實例,它可以用來了解發生錯誤的環境信息。

 

注意,Node 有計划在未來廢除unhandleRejection事件。如果Promise內部有未捕獲的錯誤,會終止進程,並且進程的退出碼不為0.

 

一般總是建議,Promise對象后面要跟catch方法,這樣可以處理Promise內部發生的錯誤。catch( )方法返回的還是一個Promise對象,因此后面還可以接着調用then()方法。

const someAsyncThing = function() {
  return new Promise(function(resolve, reject) {
    // 下面一行會報錯,因為x沒有聲明
    resolve(x + 2);
  });
};

someAsyncThing()
.catch(function(error) {
  console.log('oh no', error);
})
.then(function() {
  console.log('carry on');
});
// oh no [ReferenceError: x is not defined]
// carry on

     上邊的代碼運行完catch( )方法指定的回調函數,會接着運行后面那個then()方法指定的回調函數,如果沒有報錯,則會跳過catch( )方法 

如下:

Promise.resolve()
.catch(function(error) {
  console.log('oh no', error);
})
.then(function() {
  console.log('carry on');
});
// carry on

      上面的代碼因為沒有報錯,跳過了catch()方法,直接執行后面的then()方法。此時,要是then()方法里面報錯,就與前面的catch()無關了。

 

catch()方法之中,還能再拋出錯誤

someAsyncThing().then(function() {
  return someOtherAsyncThing();
}).catch(function(error) {
  console.log('oh no', error);
  // 下面一行會報錯,因為y沒有聲明
  y + 2;
}).catch(function(error) {
  console.log('carry on', error);
});
// oh no [ReferenceError: x is not defined]
// carry on [ReferenceError: y is not defined]

      上面代碼中,第二個catch()方法用來捕獲前一個catch()方法拋出的錯誤

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM