使用process.nextTick或setImmediate – node.js创build一个等待函数

我编写了一些Node.js,我想,来自Java背景,我应该弄清楚如何创build我自己的“等待”function。 显然,它会有所不同,因为Java被devise成multithreading而Node不是。 无论如何,我想在Node中所需的function是我想自己创build一个阻塞函数 – 如果程序中的一些布尔值没有设置,我可能要调用process.nextTick()直到布尔值被设置。

所以这将是:

  var bool = false; function foo(){ var b = baz(); } function baz(){ while(!bool){ process.nextTick(function() { return baz(arguments); }); } return {}; } function setBool(number) { setTimeout(function () { bool = false; }, number); } process.nextTick(wait); setBool(3000); 

所以这个问题是双重的:

(1)这是在Node.js中实现等待typesfunction的最好方法吗?

(2)如果我调用baz(参数)而不是baz函数(recursion)在执行方面会发生什么? 一般来说,当你想从函数X得到返回值,但函数X在返回之前自己调用几次,这是否会造成任何问题? 这不是什么大不了的事情,而且事实certificate它是相同的回报价值? 我曾经想过这个,但从来没有真正担心或调查过。

不要在Node.js中等待 “等待”阻止所有其他执行。 这是一个重要的注意事项,因为如果你阻止,那么布尔永远不能设置更改。 JavaScript,特别是在Node中,使用事件驱动的模型。 做那个,那个时候。

那么最好的办法? 这是基于意见,但这是一个方法:

 var bool = false; function foo() { console.log('Listening for true'); baz(function() { //Do something when called console.log('It\'s finally true!'); }); } function baz(callback) { setImmediate(function() { if (bool) callback(); else baz(callback); }); } foo(); setTimeout(function() { console.log('Setting to true'); bool = true; }, 4000); 

其他答案已经说明了重要的部分:不,这是行不通的。 我想发布这个提供更多的背景,为什么这不起作用。

在引擎盖下,node.js正在运行一个事件调度循环。 有一个事件队列(至less在概念上包括“应用程序启动”,“传入消息”,“套接字连接”,“文件完整”等)。 事件发生时,事件分派器将事件从队列中拉出,并调用与该事件相关的任何Javascript函数。 一旦callback函数完成,调度就会将下一个事件从队列中拉出来,处理它,等等。这是完全同步的,直到当前的事件完成,下一个事件才能被处理。

所以当你有这样的代码:

 var done = false; while (!done) { process.nextTick(function () { done = true; }); } 

怎么了? 你inputwhile循环,process.nextTick 在事件循环运行的下一个事件队列上放置一个事件进行处理。 然后你的代码循环回来,检查完成(仍然是错误的),排队等事件等等。

由于事件循环无法处理排队的事件,直到你的函数返回,事件循环卡住,process.nextTickcallback永远不会被调用。 你已经确保从来没有一个“nextTick”。

无法在纯Javascript代码中进行同步等待。 在Node.js中,你可以在C扩展中做到这一点(这是如何实现像fs.readFileSync的东西)。 有一些Javascript编译器技巧可以使用(比如stream水线或co )来编写看起来同步的代码。 但是,他们都使用asynchronouscallback模式。

我的build议是首先学习核心callback模式,以便了解它。 这是一个巨大的痛苦。 从那里调查承诺(我个人喜欢蓝鸟作为一个承诺的实现,或者如果你使用ES6,你可以使用内置的承诺)或许多asynchronous帮助程序库之一。

在Javascript中使用的典型方法是使用promise。 例如,使用“q”承诺(请参阅https://github.com/kriskowal/q ),您将拥有:

 var deferred = Q.defer(); deferred.promise.then(function(myParam) { var b = baz(); }); function baz(){ return {/*whatever you want*/}; } 

而且,在代码中的其他地方:

 deferred.resolve(myParam); 

在这个例子中,你确定只有在满足某些条件之后才会调用“baz”。 基本上,而不是设置你的布尔值为true,你“解决”延期对象。