2016-11-23 68 views
0

在我server.js文件的最後,我有以下代碼:ExpressJS錯誤處理不起作用

app.use(logErrors); 

function logErrors (err: Error, req: Request, res: Response, next: NextFunction) { 
    console.log(err); 
    mongoDal.log(err.message, err); 
    next(err); 
} 

但是這個代碼在發生錯誤時不會被達到。

我也有Node.js的錯誤處理功能,它沒有得到達到任何一個:

process.on('uncaughtException', function (err: Error) { 
    try { 
     console.log(err); 
     mongoDal.log(err.message, err); 
    } catch (err) { 

    } 
}); 

這是產生錯誤代碼:

app.get('/test_feature', function (req: Request, res: Response) { 
    makeError(); 

    res.send("Done"); 
}); 

function makeError(){ 
    throw new Error("asdasdad"); 
} 

BTW錯誤仍寫入控制檯(但不是由我的功能),並且應用程序不會崩潰。

我試圖做的是一個通用的解決方案,將捕獲每個未處理的異常在一個地方。

我在做什麼錯?

+0

你是如何定義你的請求? app.get(req,res)??? –

+0

@LucasKatayama是 – Alon

+1

Express已經有一個默認的錯誤處理程序,這可能是記錄錯誤的處理程序。我的猜測是,你正在安裝你的錯誤處理程序,它並不是最後一箇中間件,但我不能肯定地說不知道你的應用程序是如何構建的(是'server.js'的應用程序入口點,或者你是否通過其他文件啓動應用程序?) – robertklep

回答

1

下面是處理3種類型錯誤的簡短工作示例: 1)傳遞給next()處理程序, 2)throw-ed在路由處理程序中, 3)在路由處理程序調用的某個函數的回調中未處理的錯誤。 (1)和(2)使用定製錯誤中間件處理程序(A)捕獲,並且(3)由處理程序(B)捕獲。

Express有,如果它使用的呼叫next()鏈得到控制,其輸出誤差自己的錯誤處理程序(即,如果沒有定製的錯誤處理程序,或者如果它通過控制進一步使用next(err, req, res, next))。這就是爲什麼即使您的處理程序不是觸發器,仍然會在控制檯中收到錯誤消息。

如果您嘗試運行案例(1)和(2)的示例,您將看到錯誤輸出兩次 - 通過自定義處理程序(A)和默認的Express錯誤處理程序。

'use strict'; 

var express = require('express'); 
var app = express();  

var server = app.listen(8080, function() { 
    console.log('* Server listening at ' + server.address().address + ':' + server.address().port); 
}); 

// Example 1: Pass error in route handler to next() handler 
app.use('/1', function(req, res, next) { 
    console.log('* route 1'); 
    next(new Error('* route 1 error')); 
}); 

// Example 2: throw the error in route handler 
app.use('/2', function(req, res, next) { 
    console.log('* route 2'); 
    throw new Error('route 2 error'); 
}); 

// Example 3: unhandled error inside some callback function 
app.use('/3', function(req, res, next) { 
    console.log('* route 3'); 
    setTimeout(function(){ 
    throw new Error('route 3 error'); 
    }, 500); 
}); 

// Error handler A: Express Error middleware 
app.use(function(err, req, res, next) { 
    console.log('**************************'); 
    console.log('* [Error middleware]: err:', err); 
    console.log('**************************'); 
    next(err); 
}); 

// Error handler B: Node's uncaughtException handler 
process.on('uncaughtException', function (err) { 
    console.log('**************************'); 
    console.log('* [process.on(uncaughtException)]: err:', err); 
    console.log('**************************'); 
}); 

節點版本:v7.2.0

典型的錯誤是路線定義之前放置錯誤處理,而是根據你的描述,這不是這種情況。

要找到問題,您可以嘗試將自己的代碼縮小到與我的代碼大小相同,我認爲問題會變得很明顯。


UPDATE

而且,如果我嘗試運行你所提供的代碼(瑣碎的修改),它爲我工作:

'use strict'; 

var express = require('express'); 
var app = express(); 

var server = app.listen(8080, function() { 
    console.log('* Server listening at ' + server.address().address + ':' + server.address().port); 
}); 

//process.on('uncaughtException', function (err: Error) { 
process.on('uncaughtException', function (err) { 
    try { 
    console.log('*** uncaughtException:', err); 
    //mongoDal.log(err.message, err); 
    } catch (err) { 

    } 
}); 

//app.get('/test_feature', function (req: Request, res: Response) { 
app.get('/test_feature', function (req, res) { 
    makeError(); 
    res.send("Done"); 
}); 

function makeError(){ 
    throw new Error("asdasdad"); 
} 

app.use(logErrors); 

//function logErrors (err: Error, req: Request, res: Response, next: NextFunction) { 
function logErrors (err, req, res, next) { 
    console.log('*** logErrors:', err); 
    //mongoDal.log(err.message, err); 
    next(err); 
} 

結果是(堆棧跟蹤被截斷) :

* Server listening at :::8080 
*** logErrors: Error: asdasdad 
    at makeError (/home/alykoshin/sync/al-projects/dev/nmotw/400-express-error-handling/main-stackoverflow.js:32:9) 
........... 
Error: asdasdad 
    at makeError (/home/alykoshin/sync/al-projects/dev/nmotw/400-express-error-handling/main-stackoverflow.js:32:9) 
........... 

你可以在一開始看到logErrors處理器的輸出中然後將叔他輸出默認的Express錯誤處理程序。

+0

另一個建議是,在你打印出錯誤消息之前你有另一個錯誤處理程序,但是不會使用'next(err) – alykoshin

0

我認爲這個問題是在路由定義

正如你說你正在使用這個

app.get('/test_feature', function (req, res) { 
    throw new Error("asdasdad"); 
    res.send("Done"); 
}); 

嘗試使用這樣的:

app.get('/test_feature', function (req, res, next) { 
    next(new Error("asdasdad")); 
}); 

然後把res.send上錯誤處理程序...

爲什麼?

我認爲拋出一個錯誤內部的函數停止請求鏈...所以它沒有達到最後,然後你的錯誤處理程序。 如果你寫作第二種方式......你將錯誤向前移動......然後到達你的處理程序......

+0

我簡化了我的代碼。我實際上從我調用的函數中得到一個錯誤。我可以用try/catch塊來捕獲它,但我不想爲每個app.get函數添加try/catch塊。我想要一個通用的解決方案,可以在一個地方捕獲所有未處理的異常。 – Alon

+0

我已經重新制定了我的問題,使其更清晰 – Alon

+0

試試這個http://stackoverflow.com/questions/19690756/how-can-i-wrap-every-express-js-request-in-a-domain-or- trycatch –

0

如果你想在全球uncaughtException運行,你需要在沒有一個被抓的地方拋出一個錯誤,像這樣:

app.get('/test_feature', function (req: Request, res: Response) { 
    setTimeout(function() { throw new Error('oops'); }, 1000); 

    res.send("Done"); 
}); 

一個處理器中的同步throw由快遞抓住,沒有uncaughtException發生了,因爲它抓到。

而根據http://expressjs.com/en/guide/error-handling.html,錯誤處理中間件定義爲之後你的路由和其他中間件。

app.get('/test_feature', function (req: Request, res: Response) { 
    makeError(); 

    res.send("Done"); 
}); 

app.use(logErrors) 

如果你得到了錯誤的順序,當拋出一些東西時將不會調用錯誤處理程序。