【发布时间】:2019-11-26 16:29:04
【问题描述】:
在从中间件或路由处理程序调用 Express next() 或 res.send() 后,有什么方法可以捕获异步回调中发生的错误?考虑以下代码:
app.use('/throw-error', (req, res) => {
setTimeout(() => {
throw new Error('Async error causes thread death')
}, 500)
res.send('This thread is going to die...')
})
它将执行并向浏览器发送“This thread will die ...”。半秒后,它运行的 Node 线程也会崩溃。如果你碰巧正在运行一个使用 Node 的 cluster 模块的应用程序,它可能会启动一个新线程,但它还是死了。您可能会在日志中看到类似的内容:
::1 [2019-07-17T18:54:55.142Z] - [71700] 4.740 ms "GET /throw-error" 200 -
/Users/moryl/Projects/crashtest/express.js:66
throw new Error('Async error causes thread death')
^
Error: Async error causes thread death
at Timeout.setTimeout [as _onTimeout] (/Users/moryl/Projects/InSight/sources/server/config/express.js:66:13)
at ontimeout (timers.js:436:11)
at tryOnTimeout (timers.js:300:5)
at listOnTimeout (timers.js:263:5)
at Timer.processTimers (timers.js:223:10)
那个线程现在已经死了。
我的问题是,您到底是如何处理超出正常请求范围的(可能未知)异步错误,无论是设计使然还是坏事代码?如何防止线程死亡?
我不想被告知我不应该在一开始就在异步调用中做这种事情。我知道这个。我正在尝试编写防御性代码来捕捉其他人编写的“坏东西”。
【问题讨论】:
-
我认为您需要更具体地说明 “一个奇怪的异步错误”,您是在谈论随机/间歇性且难以追踪的错误吗?还是您在谈论您知道的预期错误?后者相当简单……
-
@James 我说的是未知错误。我不是想调试一些错误。我可以很容易地做到这一点。我试图让这些错误在被发现时不会对线程造成致命影响。如果这样可以减少混淆,我会从问题中删除“奇怪”这个词。
-
“未知错误”的来源并不多。大多数库(例如 socket.io)提供错误事件,你应该听一下。
-
@MichaelOryl 如果我们谈论的是 expected 错误,例如数据库连接失败或文件丢失等,那么您自然会想要处理这些,因为我们知道这些可能会发生。如果我们谈论的是 unexpected 错误,那么实际上,让应用崩溃往往比不安全更安全,因为这是我们没有预料到的,因此无法保证应用的状态。
-
@James 不,也不是在谈论预期的错误。 API 发生变化。这个应用程序中的很多代码都是由外部公司编写的——有时很糟糕。当输入系统的数据发生变化时,就会出现新问题。我正在尝试检测此类问题并更优雅地处理它们。此答案末尾的链接 (stackoverflow.com/a/57082917/1480995) 将允许我这样做。
标签: node.js express asynchronous