在Express节点中处理异常的任何其他方法?

时间:2014-10-23 08:51:46

标签: node.js express error-handling uncaught-exception winston

以下是我用于处理/记录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记录/管理所有错误:应用程序退出并且错误日志包含许多有用的信息,可以帮助解决问题。

1 个答案:

答案 0 :(得分:0)