我有一个 NodeJS 应用程序(服务器)并使用一些第 3 方 npm 模块。 另外在我的应用程序中,我有以下代码:
process.on("unhandledRejection", (reason, promise) => {
console.error(`Unhandled Rejection at: ${promise} reason: ${reason}`);
restartApp(); // ← Is this a must action?
});
似乎并不是所有的承诺都被正确拒绝,在第 3 方模块中,也许也在我的代码中。 我知道这是使用此事件处理程序的最后一个资源。
捕获此未处理拒绝事件后的问题,我需要重新启动我的应用程序吗?
将错误分为两大类很有用:操作错误和程序员错误。
操作错误是正确编写的程序遇到的(不可避免的)运行时问题,例如磁盘已满、网络连接丢失等。
程序员错误是由代码中的错误或疏忽引起的,无法处理,因为它们会导致程序进入未知状态,它们可能在您的代码中或您正在调用的模块中。
应对程序员错误的最佳做法是立即崩溃。您应该使用重新启动程序(见下文)来运行程序,该重新启动程序将在发生崩溃时自动重新启动程序。有了重新启动器,崩溃是在遇到暂时的程序员错误时恢复可靠服务的最快方法。
如果错误是操作错误,则尝试恢复或重试操作可能是有意义的(如果有意义的话)。例如,如果您收到 400 个错误,则重试 REST 请求是没有意义的,但如果您收到 500 个错误(系统可能会恢复),则可能会出现这种情况。 在这个非常有用的指南中查看更多内容:
https://www.joyent.com/node-js/product/design/errors在您的具体情况下,您正在处理 unhandledRejection,这意味着应用程序处于未定义状态...与 unhandledException 非常相似,最好的办法是清理需要完成的任何内容,然后退出或重新启动,同时记录错误(这非常重要!错误是每天、每小时还是每分钟发生?)
我建议使用过程监视器,例如
PM2或Forever。当您因错误退出时,它们可以自动重新启动,并执行许多其他很酷的操作,例如记录这些事件。 这是 Heroku 关于同一主题的另一篇精彩指南:
https://blog.heroku.com/best-practices-nodejs-errors博主(Julián Duque)甚至总结了一些处理这些事件的最佳实践:
https://blog.heroku.com/best-practices-nodejs-errors#putting-it-all-togetherconst http = require('http')
const terminate = require('./terminate')
const server = http.createServer(...)
const exitHandler = terminate(server, {
coredump: false,
timeout: 500
})
process.on('uncaughtException', exitHandler(1, 'Unexpected Error'))
process.on('unhandledRejection', exitHandler(1, 'Unhandled Promise'))
process.on('SIGTERM', exitHandler(0, 'SIGTERM'))
process.on('SIGINT', exitHandler(0, 'SIGINT'))
终止模块:
function terminate (server, options = { coredump: false, timeout: 500 }) {
return (code, reason) => (err, promise) => {
// Exit function
const exit = () => {
options.coredump ? process.abort() : process.exit(code)
}
if (err && err instanceof Error) {
// Log error information, use a proper logging library here :)
console.log(err.message, err.stack)
}
// Attempt a graceful shutdown
server.close(exit)
setTimeout(exit, options.timeout).unref()
}
}
module.exports = terminate
我认为这种对这些事件进行托管、集中处理的方式是正确的方法。