一尘不染

如何将每个Express JS请求包装在域或trycatch中

node.js

是否可以将通过express.js发出的每个请求包装到中,domaintrycatch
在此处查看trycatch信息

我正在尝试创建一种“全部捕获”(快速错误处理程序中间件不捕获异步调用),以确保将我遗漏的任何错误都发送给用户500。

如果您有一个异步函数调用(例如process.nextTick()),则它将超出express错误处理程序的范围,从而完全杀死该进程。因此,并非在所有情况下都使用快速错误处理程序。


阅读 246

收藏
2020-07-07

共1个答案

一尘不染

Express已经具有错误处理程序实现。它从connect继承它。要使用它,您需要将其添加为最后一个中间件点(最后一次app.use(…)调用)。例如:

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

app.use(app.router);
app.use(express.errorHandler());

// app.get(...), app.post(...), app.listen(...), etc.

如果要使用简单的500响应代码处理所有错误,则可以express.errorHandler()用自己的函数替换。在这种情况下,您的代码将如下所示:

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

app.use(app.router);
app.use(function(err, req, res, next){
  if (!err) return next();
  res.send(500);
});

// app.get(...), app.post(...), app.listen(...), etc.

有关此方法的更多信息,请参见代码中的表达错误示例注释。

更新

当然,您可以为每个请求使用域。您可以单独包装每个请求,也可以对路由器使用包装来处理所有异常。代码如下:

var express = require('express')
    , http = require('http')
    , app = express()
    , domain = require('domain');

//app.use(app.router);
app.use(function(req, res, next){
    var d = domain.create();
    d.on('error', function(er) {
        console.log('error, but oh well', er.message);
        res.send(500);
    });

    // explicitly add req and res
    d.add(req);
    d.add(res);

    d.run(function() {
        app.router(req, res, next);
    });
});

app.get('/', function(req,res){
    process.nextTick(function(){
        throw new Error('Check Error');
    });
});

http.createServer(app).listen(3000, function(){
    console.log('Express server listening on port 3000');
});

!!但!!
切勿在生产中使用它。这样做的原因本质上是JS抛出异常的方式。这绝对是导致应用程序泄漏的原因,并使它更加不稳定。您可以使用此类错误处理来实现自定义的关机算法(例如,关闭已打开的连接)。有关正确使用域的更多信息,请参见文档

要监视泄漏,可以使用本文中的技术。

更新2

我只是不能离开这一切。trycatch码:

var express = require('express')
    , http = require('http')
    , app = express()
    , domain = require('domain')
    , trycatch = require('trycatch');

//app.use(app.router);
app.use(function(req, res, next){
   trycatch(function(){
           app.router(req, res, next);
       }, function(er){
           console.log(er.message);
           res.send(500);
       });
});

app.get('/', function(req,res){
    process.nextTick(function(){
        throw new Error('Check Error');
    });
});

http.createServer(app).listen(3000, function(){
    console.log('Express server listening on port 3000');
});

我已经审查了的来源,trycatch没有任何魔术。仍然是泄漏的原因。trycatchdomain内幕。

2020-07-07