NodeJS異常處理uncaughtException篇
王龑 — APRIL 08, 2015
很多 NodeJS 的開發者在抱怨異常處理太麻煩,我們會透過一些列部落格梳理一下NodeJS中常見的異常處理的手段。
和大多數程式語言一樣,在 NodeJS 裡可以透過`throw`丟擲一個異常:
```
throw new Error('Catch me');
```
為了捕獲這個異常需要把程式碼包在`Try Catch`中:
```
try{
throw new Error('Catch me');
}catch(e){
// error captured
}
```
然而,由於 NodeJS 的非同步特性,上述程式碼只需稍加改造就會失效:
```
try{
process.nextTick(function my_app(){
throw new Error('Catch me');
})
}catch(e){
// never called
}
```
在現實世界裡,異常總是會產生在某個模組中。所謂模組就是能完成一個功能的單元,即使是一個簡單的函式也可以被看做一個模組。隨著專案程式碼行數增多,非同步巢狀的複雜性加強,經常會有異常沒捕獲的情況發生。一個沒有很強健壯性的 NodeJS 應用,會因為一個未捕獲的異常就整個掛掉,導致服務不可用。要改變大家覺得NodeJS是脆弱的這個認識,需要開發者加深對這門語言異常處理機制的瞭解。
##uncaughtException
`uncaughtException` 其實是 NodeJS 程式的一個事件。如果程式裡產生了一個異常而沒有被任何`Try Catch`捕獲會觸發這個事件。為了簡化問題,我們還是先看看同步情況下的例子。
```
function external() {
throw new Error('Catch me');
}
function internal() {
external();
}
internal(); //error will be thrown
```
在命令列裡執行這個程式,指令碼會在丟擲異常的那一行中斷。接下來,由於沒有`Try Catch`,異常會一直冒泡直到事件迴圈為止,而NodeJS對異常的預設處理非常簡單,處理的程式碼 *類似* 於:
```
function _MyFatalException(err){
if(!process.emit('uncaughtException',err)){
console.error(err.stack);
process.emit('exit',1);
}
}
```
NodeJS對於未捕獲異常的預設處理是: - 觸發 `uncaughtException` 事件 - 如果 uncaughtException 沒有被監聽,那麼 - 列印異常的堆疊資訊 - 觸發程式的 exit 事件
如果你正在用 NodeJS 開發伺服器,那麼你肯定不希望偶然的一個異常讓整個伺服器掛掉。那麼是不是隻要監聽了 `uncaughtException` 就可以阻止伺服器的程式退出呢? 答案是可以,**但是不要這麼做!**。看這個例子:
```
var express = require('express');
function external(cb) {
process.nextTick(function () {
throw new Error();
cb.call(null, 'sunny');
})
}
var app = express();
app.get('/weather', function (req, res) {
external(function (data) {
res.end('Weather of Beijing is ' + data);
})
})
app.listen(8018);
function noop(){}
process.on('uncaughtException', noop)
```
上面這個例子假設使用者訪問站點的時候可以看到當地的天氣,我們用 `apache2-utils` 來模擬請求
> ab -n 1000 -c 20
糟糕!請求一直在等待,記憶體上漲。原因在於`res.end` 永遠不會執行,現有的`I/O`處於等待的狀態,已經開闢的資源不僅不會被釋放,而且伺服器還在不知疲倦地接受新的使用者請求。
在 NodeJS 中處理異常是代價高昂的,而且一不小心就會導致記憶體洩露和讓應用程式處於不穩定的狀態。為了提高健壯性,我們可以用`Cluster`模式,由之而來的推薦做法是: - 針對發生異常的請求返回一個錯誤程式碼 - 出錯的Worker不再接受新的請求 - 退出關閉Worker程式
***
**本文作者系[OneAPM]()工程師王龑 ,想閱讀更多好的[技術文章](),請訪問OneAPM官方技術部落格。**
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30238867/viewspace-1630454/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 異常篇——異常處理
- NodeJS之異常處理NodeJS
- nodejs程式異常退出處理方法NodeJS
- 異常處理
- 異常-throws的方式處理異常
- 異常處理與異常函式函式
- JavaScript 異常處理JavaScript
- ThinkPHP 異常處理PHP
- React 異常處理React
- 08、異常處理
- JAVA 異常處理Java
- JAVA異常處理Java
- Abp 異常處理
- oracle異常處理Oracle
- PowerShell 異常處理
- plsql異常處理SQL
- Swift 異常處理Swift
- JS異常處理JS
- app異常處理APP
- Oracle 處理異常Oracle
- MySQL異常處理MySql
- 異常處理 (轉)
- golang - 異常處理Golang
- 異常處理2
- 異常處理1
- 異常的處理
- Java 異常處理Java
- 異常處理機制(二)之異常處理與捕獲
- JSP 異常處理如何處理?JS
- Java 異常表與異常處理原理Java
- restframework 異常處理及自定義異常RESTFramework
- windows核心程式設計---未處理異常,向量化異常處理與C++異常Windows程式設計C++
- Python 快速教程(進階篇08):異常處理Python
- Python異常處理Python
- PHP 核心 - 異常處理PHP
- Python——異常處理Python
- JAVA_異常處理Java
- SpringMVC異常處理SpringMVC