以下是我用于处理/记录Express应用程序中所有可能异常的方法。还有别的吗?
处理错误是一个微妙的问题,尤其是在处理Express时。让我们从最简单的场景开始。 想象一下,我们的应用程序如下:
console.log(ciao.ciao); // EEERRROOORRR
从控制台启动应用程序,我们得到以下结果:
console.log(ciao.ciao);
^
ReferenceError: ciao is not defined
请注意,上面的情况是un uncaught Exception的一个例子,因为我们没有执行由于错误而执行的代码。 要处理上述错误,我们可以执行以下操作:
process.on('uncaughtException', function (err) {
console.log('error', ' * we did it, we handled the error * ', err.stack.trim());
process.exit(1);
});
console.log(ciao.ciao); // EEERRROOORRR
如果我们现在启动我们获得的应用程序:
error * we did it, we handled the error * ReferenceError: ciao is not defined
请注意!!! “process.on('uncaughtException'...”将被弃用!!!
为了在弃用发生时做好准备,我们最好使用我们最喜欢的记录器的异常处理程序,它是功能强大且超级流行的winston。我们的申请成为:
var winston = require('winston');
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ handleExceptions: true }),
]
});
console.log(ciao.ciao); // EEERRROOORRR
它的输出如下:
error: uncaughtException: ciao is not defined date=Wed Oct 22 2014 16:26:53 GMT+0200 (ora legale Europa occidentale), pid=8052, uid=null, gid=null, cwd=c:\Projects\Eclipse\WEBSITE\node_taxiapplication, execPath=C:\Program Files\nodejs\node.exe, version=v0.10.26, argv=[node, c:\Projects\Eclipse\WEBSI
TE\node_taxiapplication\test2.js], rss=13479936, heapTotal=7130752, heapUsed=2760024, loadavg=[0, 0, 0],...
伟大的winston输出了许多有意义的信息来帮助我们管理错误,查看pid参数或内存信息(rss,heapTotal,...)。 winston做的另一件好事就是退出应用程序,如果没有被捕获的例外,那就好了。
让我们的应用程序成为Express Server 我们的申请成为:
var winston = require('winston');
var express = require('express');
var app = express();
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ handleExceptions: true }),
]
});
app.get('/', function(req, res, next) {
console.log(ciao.ciao); // EEERRROOORRR
});
app.listen(3000);
启动服务器并询问浏览器http://localhost:3000
浏览器:
ReferenceError: ciao is not defined at Object.handle (c:\Projects\Eclipse\WEBSITE\node_taxiapplicatio...
并且它仍在运行的应用程序在Web服务器上出现错误时不是一个好主意。
到底哪里是winston Exception Handler?
Winston没有处理上面的错误,因为它是由Express处理的,这是因为错误在以下Express路由处理程序的范围内:
function(req, res, next) {
console.log(ciao.ciao); // EEERRROOORRR
});
So winston is out of the game in case of error inside of an Express route handler
我们想要实现的是使用winston和应用程序退出此错误但要达到我们的目标,我们需要在“内部”Express中发生错误时执行我们的代码。为此,我们将使用Express错误中间件,如下所示:
var winston = require('winston');
var express = require('express');
var app = express();
var logger = new (winston.Logger)({
transports: [
new (winston.transports.Console)({ handleExceptions: true }),
]
});
app.get('/', function(req, res, next) {
console.log(ciao.ciao); // EEERRROOORRR
});
app.use(function(err, req, res, next) {
logger.log('error', ' * logged by winston * ', err.stack.trim());
process.exit(1);
});
app.listen(3000);
如果我们向我们的浏览器http://localhost:3000
询问,我们会获得应用程序退出并在控制台上获取以下内容,这是由winston抛出的:
error: * logged by winston * ReferenceError: ciao is not defined
不幸的是,在这种情况下,我们无法获得winston在直接处理异常时输出的所有信息,但在列表中我们也可以控制Express处理的错误。
但我希望winston在直接处理异常时提供的所有信息
好的,我们试试吧!我们必须找到一种让Express失去对Exception的控制的方法。我们在上面说过,Express会在路由处理程序的范围内处理异常:
app.get('/', function(req, res, next) {
console.log(ciao.ciao);
});
让我们检查在Express路由处理程序中包含的异步函数内发生错误时会发生什么:
app.get('/', function(req, res, next) {
setTimeout(function () {
console.log(ciao.ciao);
});
});
启动应用:
var winston = require('winston');
var express = require('express');
var app = express();
var logger = new (winston.Logger)({
transports: [ new (winston.transports.Console)({ handleExceptions: true }) ]
});
app.get('/', function(req, res, next) {
setTimeout(function () {
console.log(ciao.ciao); // EEERRROOORRR
}, 1);
});
app.listen(3000);
并请求http://localhost:3000
我们观察应用程序退出并在控制台上:
error: uncaughtException: ciao is not defined date=Thu Oct 23 2014 09:52:01 GMT+0200 (ora legale Europa occidentale), pid=5952, uid=null, gid=null, cwd=c:\Projects\Eclipse\WEBSITE\node_taxiapplication, execPath=C:\Program Files\nodejs\node.exe, version=v0.10.26, argv=[node, c:\Projects\Eclipse\WEBSI
TE\node_taxiapplication\test2.js], rss=18325504, heapTotal=15453568, heapUsed=4883192,
Hej,Express没有处理上面的错误,但是winston做了(我们在输出中有内存细节)。这是因为错误不是在Express作用域内发生,而是在异步函数作用域内发生。 因此,我们需要的是在异步函数范围内的错误中转换Express作用域中的错误。 Hej我们可以做到这一点,事实上我们已经能够运行我们的代码来管理Express错误。 我们的策略是在Express错误中间件(其中有我们的代码来处理Express错误)中插入一个异步setTimeout(1ms延迟),并在setTimeout内部抛出相同的错误到达中间件作为参数。
var winston = require('winston');
var express = require('express');
var app = express();
var logger = new (winston.Logger)({
transports: [ new (winston.transports.Console)({ handleExceptions: true }) ]
});
app.get('/', function(req, res, next) {
console.log(ciao.ciao); // EEERRROOORRR
});
app.use(function(err, req, res, next) {
res.send('Arrrghhh!!! The Server is at the moment down.');
setTimeout(function () {
throw new Error(err.stack.trim()); // <<<--- TRICK
}, 1);
});
app.listen(3000);
请求http://localhost:3000
我们在浏览器上有响应“Arrrghhh !!! ...”,应用程序退出并在我们获得的控制台上:
error: uncaughtException: ReferenceError: ciao is not defined date=Thu Oct 23 2014 10:00:51 GMT+0200 (ora legale Europa occidentale), pid=5792, uid=null, gid=null, cwd=c:\Projects\Eclipse\WEBSITE\node_taxiapplication, execPath=C:\Program Files\nodejs\node.exe, version=v0.10.26, argv=[node, c:\Projec
ts\Eclipse\WEBSITE\node_taxiapplication\test2.js], rss=18489344, heapTotal=15453568, heapUsed=5115092,...
我们获得通过winston记录/管理所有错误:应用程序退出并且错误日志包含许多有用的信息,可以帮助解决问题。
答案 0 :(得分:0)