了解在node.js中的尝试和捕获
我是新来的编码。 尝试了解为什么try … catch不应该在node.js中工作。 我创build了一个例子,但与预期相反,尝试…赶上似乎工作。 我的理解错在哪里? 请帮忙。
function callback(error) { console.log(error); } function A() { var errorForCallback; var y = parseInt("hardnut"); if (!y) { throw new Error("boycott parsley"); errorForCallback = "boycott parsley for callback"; } setTimeout(callback(errorForCallback),1000); } try { A(); } catch (e) { console.log(e.message); } // Output: boycott parsley // Synchronous behaviour, try...catch works
———–例子重新框架,以反映我的理解后,阅读下面的答案———–
function callback(error) { console.log(error); } function A() { var errorForCallback; setTimeout(function(){ var y = parseInt("hardnut"); if (!y) { // throw new Error("boycott parsley"); errorForCallback = "boycott parsley for callback"; } callback(errorForCallback); }, 1000); } try { A(); } catch (e) { console.log(e.message); } // Output: boycott parsley for callback // Asynchronous behaviour // And if "throw new Error" is uncommented, // then node.js stops
try-catch方法是与同步代码完美配合的。 并不是所有在Node.js中做的编程都是asynchronous的,所以在你编写的同步代码中你可以完全使用try-catch方法。 另一方面,asynchronous代码不能这样工作。
例如,如果你有两个这样的函数执行
var x = fooSync(); var y = barSync();
你会期待三件事,首先是barSync()
将被执行,直到fooSync()
完成,并且你会希望x
将包含在执行barSync()
之前执行fooSync
所返回的任何值。 你也会期望,如果fooSync
抛出exception, barSync
永远不会执行。
如果你想在fooSync()
附近使用try-catch,你可以保证如果fooSync()
失败,你可以捕获这个exception。
现在,条件完全改变,如果你有这样的代码:
var x = fooAsync(); var y = barSync();
现在想象一下,当在这个场景中调用fooAsync()
时,它并没有被实际执行。 它只是计划在稍后执行。 就好像节点会有待办事项列表一样,在这个时候它正忙于运行你的当前模块,当它发现这个函数调用,而不是运行它,它只是把它添加到它的待办事项列表的末尾。
所以,现在你不能保证barSync()
会在fooAsync()
之前运行,事实上,它可能不会。 现在你不控制执行fooAsync()
的上下文。
所以,在调度fooAsync()
函数之后,它立即移动到执行barSync()
。 那么, fooAsync()
返回什么? 在这一点上什么也没有,因为它还没有运行。 所以上面的x
可能是未定义的。 如果你想把try-catch放在这段代码中,那就没有意义了,因为函数不会在这个代码的上下文中执行。 稍后将会执行,当Node.js检查其待办事项列表中是否有待处理的任务时。 它将在不断检查这个待办事项列表的另一个例程的上下文中执行,而这个唯一的执行线程称为事件循环。
如果你的函数fooAsync()
失败,在运行事件循环的线程的执行环境中会失败,因此它不会被你的try-catch语句捕获,在那个时候,上面的模块可能已经完成了执行。
所以,这就是为什么在asynchronous编程中你不能得到一个返回值,你也不能期望做一个try-catch,因为你的代码是在别的地方,而不是你认为你调用它的地方。 这就好像你可以做这样的事情:
scheduleForExecutionLaterWhenYouHaveTime(foo); var y = barSync();
这就是asynchronous编程需要其他技术来确定代码在最终运行时发生了什么的原因。 通常这是通过callback通知的。 你可以定义一个callback函数,这个callback函数的细节是失败的(如果有的话)或者你的函数产生了什么,然后你可以对此做出反应。