我有一个node.js服务器,我希望能够处理异常而不会崩溃,我有类似下面的代码。我想知道的是,所有事件驱动的精彩和回调以及lambdas以及所有这些,我的例外仍然会被我的主要切入点捕获?
try {
http.get(..., function(results) {
// Might get an exception here
results.on('data', function () {
// Might also get an exception here
});
results.on('end', function () {
// Might also get an exception here
});
});
} catch(e) {
// Will the exceptions from the lambdas be caught here?
console.log('Nicely caught error: (' + e.name + '): ' + e.message);
}
由于
答案 0 :(得分:8)
这取决于控制流程。 Node.js强调异步,并且异步性的一个主要缺点是代码不会以您可能习惯使用同步语言的方式流动。
在同步语言中,当函数等待某些数据时,调用者被阻止。这使程序员的工作变得相当简单,因为可以保证当等待数据的函数返回时,将有数据供调用者使用。
它与异步语言或非阻塞I / O完全相反。在这种情况下,调用程序在函数调用期间被阻塞,但函数不必在返回之前等待数据或I / O完成。这使得程序员的工作稍微困难一些,因为当函数调用返回时,无法保证是否有可用的数据。因此,非阻塞I / O通常意味着在数据可用时调用的回调函数。
try/catch
块可以与调用堆栈一起使用。也就是说,当抛出异常时,运行时将展开调用堆栈,直到找到围绕引发异常的调用的catch
块。但是,由于http.get
是一个非阻塞调用,它会在注册一些回调后立即退出并继续处理。回调在单独的“线程”中调用,因此调用不嵌套在原始try/catch
块中。
图表真的有助于解释这里的事情,但不幸的是我没有可用的。
答案 1 :(得分:2)
node.js标准库的错误处理样式是调用相同的回调,但是传递表示错误的非null第一个参数。如果异步代码中存在异常情况,请将其保留为该格式。
throw会爬上调用者链,通常不知道回调正在做什么(例如,tcp层不关心它的数据被解析为http)。可抛出的异常非常适合异步编程。
答案 2 :(得分:2)
在您的示例代码中,http.get回调中抛出的任何潜在异常都不会落入catch块。当数据可供读取时,回调堆栈是从节点的事件循环构建的。
有一种方法可以捕获节点中未捕获的异常:
process.on("uncaughtException", function (err) {
console.log("uncaught exception: " + err);
});
这将为您的示例提供一些工作,具体取决于异常的位置。
麻烦的是,未被捕获的异常可以以令人惊讶的方式解开节点的内部工作,所以你真的不想依赖于此。以可以处理它们的方式捕获所有可能异常的唯一可靠方法是在事件循环的每个入口点附近使用try / catch。
这听起来很乏味,但通常并不坏。在您的示例程序中,您使用节点的API进行HTTP请求,这仍然是一个非常低级的接口。对于大多数情况,您希望将此异常捕获功能包装一次并将其用作库。