了解在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函数的细节是失败的(如果有的话)或者你的函数产生了什么,然后你可以对此做出反应。