访问 app.use 外部的请求/响应对象,用于 unhandledRejection 事件处理程序

问题描述

到目前为止,我已经检查过以通用方式处理 promise 的错误,unhandledRejection 事件处理程序是最好的方法。就像下面一样:

process.on('unhandledRejection',(reason,promise) => {
console.log('error: unhandledRejection');
});

现在,当我想访问此事件处理程序中的请求和响应对象时,挑战就来了。这样我就可以以通用方式生成 500 响应,因此我不需要在项目中的任何地方添加 promise 异常处理。

有人建议我使用:

app.use(function (req,res,next) {
process.on('unhandledRejection',function (reason,promise) {
console.error("Here I can access request objects.")
// Unregister unhandledRejection
});
});

但在上述情况下,事件侦听器将被多次注册,并且只有在发生异常时才会取消注册。由于事件会被多次注册,所以代码console.error("Here I can access request objects."))会被多次触发。

有什么建议吗?如果我可以在 app.use 之外访问请求和响应对象?

提前致谢!

解决方法

默认 express 会处理错误。通过快递文件:

Express 带有一个嵌入式错误处理程序,它将处理应用程序中可能发生的任何错误。这个默认的错误处理中间件函数添加在中间件函数栈的末尾。

next() 如果你给函数一个错误并且没有在自定义错误处理程序中处理它,这个错误由​​嵌入的错误处理程序处理;错误通过堆栈跟踪打印在客户端上。生产环境中不包含堆栈跟踪。

将环境变量的 NODE_ENV 值设置为 production 以在生产模式下运行应用程序。

当打印错误时,会在响应中添加以下信息:

  • res.statusCode err.status 字段的值来自该字段 (或 err.statusCode)。如果此值不在 4xx 或 5xx 范围内, 它将设置为 500。

  • res.statusMessage 字段根据 状态码。

  • 如果在生产模式下,正文(body)变成了 状态码消息,否则为 err.stack。

  • err.headers 对象中指定的任何标头。

next() 如果在开始写入响应后调用函数时出错(例如,如果在将响应传输到客户端时遇到错误),默认的 Express 错误处理程序将关闭连接并使请求失败.

当您添加自定义错误处理程序时,如果标头已经发送到客户端,您应该授权默认的 Express 错误处理程序:

function errorHandler (err,req,res,next) {
  if (res.headersSent) {
    return next(err)
  }
  res.status(500)
  res.render('error',{ error: err })
}

在代码中有错误的情况下多次调用 next() 函数可能会触发默认错误处理程序,即使自定义错误处理程序中间件已就位。

这很容易导致内存泄漏:

app.use(function (req,next) {
process.on('unhandledRejection',功能(原因,承诺){
console.error("在这里我可以访问请求对象。") // 取消注册 unhandledRejection
}); });

此外,您无法访问 'unhandledRejection' 中的响应对象,如果 express 可以处理该对象以向用户发送 '500' 状态代码,那么您为什么要访问该对象。无论何时何地需要,捕捉承诺总是一个好习惯。但是,如果仍然没有涵盖某些承诺,那么也有一些库可以处理它,例如:express-promise-router,express-async-errors

我们可以在 express 错误处理程序中使用 err 参数发出有意义的错误响应,并将响应发送给用户。例如,

app.use((err,next) => {
  if (err.name === 'CustomError' && err.message === 'EmptyResponse') {
    return res.status(404).send('Not Found');
  }
  // ... more error cases...
  return res.status(500).send('Internal Server Error');
});

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...