[英]ExpressJS error handling doesn't work
在我的 server.js 文件的最后,我有以下代碼:
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");
}
順便說一句,錯誤確實寫入了控制台(但不是我的功能),並且應用程序不會崩潰。
我正在嘗試制作一個通用解決方案,它將在一個地方捕獲每個未處理的異常。
我做錯了什么?
下面是處理 3 種類型錯誤的簡短工作示例:1) 傳遞給next()
處理程序,2) 在路由處理程序內部拋出,3) 從路由處理程序調用的某些函數的回調中未處理的錯誤。
(1) 和 (2) 使用自定義錯誤中間件處理程序 (A) 捕獲,(3) 由uncaughtException
處理程序 (B) uncaughtException
。
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
典型的錯誤是將錯誤處理程序放在路由定義之前,但根據您的描述,情況並非如此。
要定位問題,您可以嘗試將自己的代碼減少到與我相同的大小,我認為,問題會變得很明顯。
更新
此外,如果我嘗試運行您提供的代碼(稍作修改),它對我有用:
'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 錯誤處理程序的輸出。
注意:您的錯誤處理程序中間件必須有 4 個參數:error、req、res、next。 否則你的處理程序不會觸發。
我一直在解決這個問題,直到我發現了這一點。
我認為問題出在路由定義上
正如你所說,你正在使用這個
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 放在錯誤處理程序上...
為什么?
我認為在函數內拋出一個錯誤會停止請求鏈......所以它不會到達最后,然后是你的錯誤處理程序。 如果你用第二種方式寫......你將錯誤向前移動......然后到達你的處理程序......
如果你想讓全局uncaughtException
運行,你需要在沒有人捕捉到的地方拋出一個錯誤,像這樣:
app.get('/test_feature', function (req: Request, res: Response) {
setTimeout(function () { throw new Error('oops'); }, 1000);
res.send("Done");
});
處理程序中的同步throw
被 express uncaughtException
,當它被uncaughtException
時根本沒有發生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)
如果您得到錯誤的順序,則在拋出某些內容時將不會調用錯誤處理程序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.