promise-不使用catch出現warning的原因


今天在使用node運行js文件時,返回了下面的錯誤和警告,警告部分主要是因為使用了promise,但是沒有使用catch來捕捉錯誤.
更詳細的解釋在下面,這是nodejs文檔的process模塊的一部分
用戶deMBP:loveToken 用戶$ node test.js
{ Error: connect ECONNREFUSED 10.240.100.88:8081
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:14)
  errno: 'ECONNREFUSED',
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: '10.240.100.88',
  port: 8081 }
(node:3718) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 10.240.100.88:8081
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1159:14)
(node:3718) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3718) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.


'rejectionHandled' 事件——異步
如果有 Promise 被 rejected,並且此 Promise在 Node.js 事件循環的下次輪詢及之后期間,被綁定了一個錯誤處理器(即使用了catch的話,就會觸發這個事件)(例如使用 promise.catch()),會觸發 'rejectionHandled' 事件。
此事件監聽器的回調函數使用 rejected 的 Promise 引用,作為唯一入參。
Promise 對象應該已經在 'unhandledRejection' 事件觸發時被處理,但是在被處理過程中獲得了一個 rejection 處理器。
對於 Promise 鏈,沒有概念表明在 Promise 鏈的哪個地方,所有的 rejection 總是會被處理。 由於本來就是異步的,一個 Promise rejection 可以在將來的某個時間點被處理-可能要遠遠晚於 'unhandledRejection' 事件被觸發及處理的時間。
另一種表述的方式就是,與使用同步代碼時會出現不斷增長的未處理異常列表不同,使用 Promise 時,未處理異常列表可能會出現增長然后收縮的情況。
在同步代碼情況下,當未處理異常列表增長時,會觸發 'uncaughtException' 事件。
在異步代碼情況下,當未處理異常列表增長時,會觸發 'unhandledRejection' 事件,當未處理列表收縮(就是被解決了)時,會觸發 'rejectionHandled' 事件。
例如:
const unhandledRejections = new Map();
process.on('unhandledRejection', (reason, p) => {//未處理
  unhandledRejections.set(p, reason);
});
process.on('rejectionHandled', (p) => {//已處理
  unhandledRejections.delete(p);
});
在上述例子中,unhandledRejections 會隨着時間增加和縮減,表明 rejection 開始是未被處理狀態,然后變成已處理狀態。 可以定時(對於需長期運行的應用,這個可能是最好的方式)或當進程結束時(對腳本的應用可能是最方便的),在錯誤日志中記錄這些錯誤信息。
'uncaughtException' 事件——同步
如果 Javascript 未捕獲的異常,沿着代碼調用路徑反向傳遞回事件循環,會觸發 'uncaughtException' 事件。 Node.js 默認情況下會將這些異常堆棧打印到 stderr 然后進程退出。 為 'uncaughtException' 事件增加監聽器會覆蓋上述默認行為。
'uncaughtException' 事件監聽器的回調函數,使用 Error 對象作為唯一參數值。
例如:
process.on('uncaughtException', (err) => {
  fs.writeSync(1, `捕獲到異常:${err}\n`);
});

setTimeout(() => {
  console.log('這里仍然會運行。');
}, 500);

// 故意調用一個不存在的函數,應用會拋出未捕獲的異常。
nonexistentFunc();
console.log('這里不會運行。');
注意:正確地使用 uncaughtException
需要注意,如果打算使用 'uncaughtException' 事件作為異常處理的最后補救機制,這是非常粗糙的設計方式。 此事件不應該當作 On Error Resume Next(出了錯誤就恢復讓它繼續)的等價機制。 未處理異常本身就意味着應用已經處於了未定義的狀態。如果基於這種狀態,嘗試恢復應用正常進行,可能會造成未知或不可預測的問題。
此事件的監聽器回調函數中拋出的異常,不會被捕獲。為了避免出現無限循環的情況,進程會以非零的狀態碼結束,並打印堆棧信息。
如果在出現未捕獲異常時,嘗試去恢復應用,可能出現的結果與電腦升級時拔掉電源線出現的結果類似 -- 10次中有9次不會出現問題,但是第10次可能系統會出現錯誤。
正確使用 'uncaughtException' 事件的方式,是用它在進程結束前執行一些已分配資源(比如文件描述符,句柄等等)的同步清理操作。 觸發 'uncaughtException' 事件后,用它來嘗試恢復應用正常運行的操作是不安全的。
想讓一個已經崩潰的應用正常運行,更可靠的方式應該是啟動另外一個進程來監測/探測應用是否出錯, 無論 uncaughtException 事件是否被觸發,如果監測到應用出錯,則恢復或重啟應用。

'unhandledRejection' 事件——異步
如果在事件循環的一次輪詢中,一個 Promise 被 rejected,並且此 Promise 沒有綁定錯誤處理器(就是沒有對它進行處理的操作),’unhandledRejection 事件會被觸發。 當使用 Promise 進行編程時,異常會以 "rejected promises" 的形式封裝。Rejection 可以被 promise.catch() 捕獲並處理,並且在 Promise 鏈中傳播。'unhandledRejection 事件在探測和跟蹤 promise 被 rejected,並且 rejection 未被處理的場景中是很有用的。
此事件監聽器的回調函數被傳遞如下參數:
    •    reason <Error> | <any> 此對象包含了 promise 被 rejected 的相關信息(通常是一個 Error 對象)。
    •    p 被 rejected 的 promise 對象。
例如:
process.on('unhandledRejection', (reason, p) => {
  console.log('未處理的 rejection:', p, '原因:', reason);
  // 記錄日志、拋出錯誤、或其他邏輯。
});

somePromise.then((res) => {
  return reportToUser(JSON.pasre(res)); // 故意輸錯 `pasre`。
}); // 沒有 `.catch` 或 `.then`。
如下代碼也會觸發'unhandledRejection'事件
function SomeResource() {
  // 將 loaded 的狀態設置為一個 rejected promise。
  this.loaded = Promise.reject(new Error('錯誤信息'));
}

const resource = new SomeResource();
// resource.loaded 上沒有 .catch 或 .then。
在例子中,可以像在其他 'unhandledRejection' 事件的典型場景中一樣,跟蹤開發者錯誤導致的 rejection。 為了解決這樣的錯誤,resource.loaded 中可以加一個不做任何操作的 .catch(() => { }) 處理器, 這樣可以阻止 'unhandledRejection' 事件的觸發。或者也可以使用 'rejectionHandled' 事件來解決。


免責聲明!

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



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