bli*_*ter 6 error-handling node.js
我正在使用来自 npm 的第 3 方包,该包又连接到 IP 地址 XXXX 上的某些外部 API,并因以下错误而崩溃。原因很明显了,网络暂时宕机了,BOOM我的整个程序都停止了:
events.js:177
throw er; // Unhandled 'error' event
^
Error: connect ENETUNREACH X.X.X.X:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1054:14)
Emitted 'error' event at:
at Socket.socketErrorListener (_http_client.js:410:9)
at Socket.emit (events.js:200:13)
at emitErrorNT (internal/streams/destroy.js:91:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)
at processTicksAndRejections (internal/process/task_queues.js:84:9) {
errno: 'ENETUNREACH',
code: 'ENETUNREACH',
syscall: 'connect',
address: 'X.X.X.X',
port: 80
}
Run Code Online (Sandbox Code Playgroud)
我故意不说是 npm 上的哪个模块导致了问题,因为我无法控制第 3 方模块作者在做什么。如果我向他们抱怨,他们可能会或可能不会修复它,但我的编码生活需要继续。即使我调用的任何代码存在编码错误,也不应该使我的调用脚本完全崩溃。应该有一种方法让我在它完全限制我的风格之前抓住这种情况。
我尝试过的:我小心翼翼地使用错误处理,try/catch围绕任何 3rd 方异步库调用等。示例:
var ThirdPartyModule = require("thirdPartyModule");
try {
await ThirdPartyModule.doIt("some", "params");
} catch (err) {
console.log("Ok so the module call failed. Let's try something else here, but don't abort my script please!");
}
Run Code Online (Sandbox Code Playgroud)
在catch做什么也不做。每次调用模块并发生连接错误时,它都会用上面的“throw er;”完全坦克我的整个程序。
我的问题是,我可以围绕对库的调用编写哪些额外的“包装器”代码来“捕获”不属于我的代码中的任何崩溃,以便我的代码继续执行?
我仍然是 nodejs 的菜鸟,所以我想我错过了一些在这里起作用的更伟大的 nodejs 概念。我来自 C++ 或 Java,所以每当这些语言中的某些东西崩溃时,我总是可以 catch() 它,所以我很困惑模块如何在我的主脚本中“逃脱”try/catch。
请注意,我不是在寻找诸如“您应该确保始终连接到 Internet,这就是 ENETUNREACH 的意义所在”之类的答案。相反,我试图了解如何成为我正在调用的“子模块”的主人,即捕捉他们的错误,或者如果我不能成为他们的主人,我想了解为什么我想要的在 nodejs 中是不可能的.
谢谢!
编辑:在下面链接到的类似问题中,评论者建议添加一个process.on("uncaughtException")处理程序。我现在就试试这个。
如果这是正确的解决方案,请将其作为答案发布并解释基本概念。为什么我不能仅仅依靠try/catch这是改革后的 Java 程序员会做的事情?npm 上模块的作者做了什么来不将错误传递到他的异步函数链中?
编辑 2:也许我的问题最终是重复Catch all uncaughtException for Node js 应用程序- 我很想解释一下为什么必须像这样全局捕获深层崩溃,并且不会渗透到调用者链上。是不是因为第 3 方编码人员犯了错误,并且未能将其代码中可能出现的所有可能问题转换为throw异步代码中的适当s?
编辑 3:好的,我设法找到了问题所在。我使用的图书馆不是罪魁祸首。它无辜地调用并承诺了一个第四方库(也在 npm 上),它通过http.request(). 只是那个第4方库的作者忘记安装request.on('error')回调,所以当互联网连接出现问题时(从来没有发生过,对吧!),这成为一种无法处理的情况。第 3 方库永远不会从第 4 方库获得预期的“出错时”回调,因此永远无法保证这种错误情况。相反,该错误在 nodejs ether 中未得到处理,导致我的整个脚本崩溃。所以有...
绝对不对库内代码的结构做出任何假设,您将陷入以下困境:
process.on('uncaughtException', function (err) {
//do something
});
Run Code Online (Sandbox Code Playgroud)
原因是:如果库自始至终都使用 Promise,那么 try/catch 块就会捕获它。库内抛出错误的部分很可能位于回调内。
异步代码的最佳实践应该是向回调返回错误,返回被拒绝的 Promise 或在异步块内抛出,并且永远不要使用回调或原始 Promise 在函数内抛出。然而,这似乎极有可能正是正在发生的事情。此时没有办法优雅地处理错误,只能包罗万象uncaughtException。
本质上,在 Promise 或传统异步回调内抛出错误的情况下,代码会抛出同步错误,并且没有同步 try/catch 块来处理它。而且你不能从模块外部注入一个。
简而言之,该错误没有“适当”的机制可以处理。第三方模块编写者应该感到羞耻。
| 归档时间: |
|
| 查看次数: |
1581 次 |
| 最近记录: |