如何在express 4中的未捕获错误后呈现500响应?

app.get('/', function(req, res) { doSomethingAsync(function(err) { throw new Error('some unexpected/uncaught async exception is thrown'); }) }) Possibly unhandled Error: some unexpected/uncaught async exception is thrown at ...stacktrace...:95:9 From previous event: at ...stacktrace...:82:6) at ...stacktrace...:47:6) at ...stacktrace...:94:18) 

我尝试了一堆域中间件,但他们都只为快递3.我目前正在expression4.5,我想知道如果明确已经改变该域名不再起作用。

目前,当引发exception时,响应基本上会挂起,直到超时。

正如你所发现的, try / catch一个asynchronous函数是行不通的。 expression式 4中的域名应该工作得很好(或者expression3,或者直接http,不pipe)。 我从来没有使用任何试图实现域处理的快递中间件,所以我不能说他们做得好不好。

我build议你自己实施域名处理。 它没有那么坏。 使用域的更好的例子之一就是在节点关于域的文档中 (不是第一个不好的例子,第二个好的例子)。 我强烈build议阅读这些文档。

基本的想法很简单:

  1. 创build一个域
  2. 添加error handling程序
  3. 调用domain.run(function() { ... })把你想要的代码放入该运行的callback中。

一个非常简单的(也是非常本地化的)例子:

 // This will alwas throw an error after 100ms, but it will still // nicely return a 500 status code in the response. app.get('/', function(req, res) { var d = domain.create(); d.on('error', function(err) { res.status(500).send(err.message); }); d.run(function() { setTimeout(function() { throw new Error("some unexpected/uncaught async exception"); }, 100); }); }); 

所以,这样做可能会有效果,但对于您的情况来说可能已经足够了,但这不是最好的解决scheme( 如果您已经阅读了文档,您可能会注意到这是一个非常糟糕的例子 )。 问题是(从文档再次):

由于JavaScript在JavaScript中的工作原理,几乎没有任何方法可以安全地“捡起你离开的地方”,而不会泄漏引用或创build其他某种不明确的状态。

最好的解决scheme(据我所知)是做什么build议在节点文档。 他们build议的基本思想是使用cluster (或类似的东西)启动多个工作进程,从主进程运行您的Web服务器。 在每个工作进程中,设置一个域,在发生错误时会很好地发回500状态,然后退出。 然后,在主stream程中,检测员工何时退出并简单地启动新员工。

这样做是消除任何问题,只要在发生错误时重新启动整个过程,但只有在正确处理之后才能“拾取离开的位置”。

在SO答案中join一个例子可能有点多,但是在node docs中确实有一个很好的例子。 如果你还没有, 去看看它。 🙂

假设你得到的错误是在路由器或者控制器里,在你的应用configuration的最后,在听之前

 app.use(function(err, req, res) { res.status(err.status || 500); // if you using view enggine res.render('error', { message: err.message, error: {} }); // or you can use res.send(); }); 

你的应用程序将捕获任何未被捕获的路由器错误,并将呈现“错误”页面

顺便说一下,不要忘记在你的路由器初始化中包含“下一步”


编辑

 app.get('/', function(req, res, next) { try { signin(req.query.username, req.query.password, function(d){ if (d.success) { req.session.user = d.data; } res.end(JSON.stringify(d)); }); } catch(e) { next(e); } } 

希望它有帮助