5

下面是我用来处理/记录 Express 应用程序中所有可能的异常的方法。还有什么办法吗?

错误处理是一个微妙的问题,尤其是在处理 Express 时。让我们从最简单的场景开始。想象一下我们的应用程序如下:

console.log(ciao.ciao);    // EEERRROOORRR

从控制台启动应用程序,我们得到以下信息:

console.log(ciao.ciao);
            ^
ReferenceError: ciao is not defined

请注意,上述情况是一个未捕获异常的示例,因为我们没有因错误而执行编写的代码。要处理上述错误,我们可以执行以下操作:

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 没有处理上述错误,因为它已由 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,

嘿,Express 没有处理上述错误,但 winston 处理了(我们在输出中有内存详细信息)。这是因为错误没有发生在 Express 范围内,而是发生在异步函数范围内。因此,我们需要将 Express 范围内的错误转换为异步函数范围内的错误。我们可以做到这一点,事实上我们已经能够运行我们的代码来管理 Express 错误。我们的策略是在 Express 错误中间件(其中有我们处理 Express 错误的代码)和 setTimeout 中插入一个异步 setTimeout(1ms 延迟),以将到达中间件的相同错误作为参数抛出。

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

4

1 回答 1

0

试试这个以更好地处理错误。

https://github.com/expressjs/errorhandler

https://www.npmjs.org/package/express-error-handler

于 2014-10-23T10:33:04.550 回答