在Node / Express中的异步函数中捕获错误

Mic*_*ryl 8 asynchronous node.js express

是否有任何方法可以捕获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...')
})
Run Code Online (Sandbox Code Playgroud)

它将执行并将“此线程即将死...”发送给浏览器。半秒钟后,它也会使正在运行的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)
Run Code Online (Sandbox Code Playgroud)

该线程现在已死。

我的问题是,无论是通过设计还是通过错误的代码,您如何处理超出正常请求范围的(可能未知)异步错误?如何防止线程死亡?

我不想被告知我不应该在异步调用中做这种事情。我知道这个。我正在尝试编写防御性代码以捕获其他人编写的“坏东西”。

Jon*_*lms 1

我的问题是,你到底如何处理超出正常请求范围的异步错误,无论是设计...

您仍然希望处理异步代码中的错误,即使它在设计上被触发并被遗忘。向每个独立任务添加一个try { } catch { }或。.catch使用异步代码,Promises 和async/await可以帮助您(因为它们将独立的回调分组到任务中,然后您可以处理每个任务的错误):

const timer = ms => new Promise(res => setTimeout(res, ms));

async function fireAndForgetThis() {
  await timer(500);
  throw new Error('Async error doesn't cause thread death, because its handled properly')
}

 fireAndForgetThis()
   .catch(console.error); // But always "handle" errors
Run Code Online (Sandbox Code Playgroud)

...或者通过错误的代码?

修复错误的代码。

如何防止线程死亡?

这不是你想要阻止的事情。如果发生错误且未处理,您的应用程序将进入未计划状态。继续执行可能会产生更多问题。你不想要这样。您希望防止未处理的拒绝/未处理的错误本身(通过正确处理)。


当然,有些情况是您无法处理的,例如,如果与支持数据库的连接断开。在这种情况下,NodeJS 崩溃,导致监控唤醒 DevOps,使数据库恢复运行。崩溃也是处理错误的一种形式;)


如果您读到这里,并且仍然想处理未处理的错误,请不要这样做。好吧,你可能有你的理由,就这样吧