Javascript 使用process.nextTick或setImmediate-node.js创建等待函数
我正在编写一些Node.js,我认为,从Java背景来看,我应该知道如何创建自己的“等待”功能。显然,它会有点不同,因为Java被设计成多线程的,而Node则不是。无论如何,我想要在Node中实现的功能是,我想自己创建一个阻塞函数——这样,如果程序中的某个布尔值没有设置,我可能想调用Javascript 使用process.nextTick或setImmediate-node.js创建等待函数,javascript,node.js,recursion,Javascript,Node.js,Recursion,我正在编写一些Node.js,我认为,从Java背景来看,我应该知道如何创建自己的“等待”功能。显然,它会有点不同,因为Java被设计成多线程的,而Node则不是。无论如何,我想要在Node中实现的功能是,我想自己创建一个阻塞函数——这样,如果程序中的某个布尔值没有设置,我可能想调用process.nextTick(),直到布尔值被设置为止 因此,这将是: var bool = false; function foo(){ var b = baz(); }
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中实现等待类型功能的最佳方法吗
(2) 如果我调用baz(arguments)而不是baz函数(递归),那么在执行方面会发生什么?通常,当您希望从函数X返回值,但函数X在返回之前调用了自己几次时,这会带来任何问题吗?这没什么大不了的,结果是相同的回报值吗?我以前考虑过这一点,但从未真正担心或调查过。不要在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);
在Javascript中实现这一点的典型方法是使用承诺。例如,有了“q”承诺(参见),您将:
var deferred = Q.defer();
deferred.promise.then(function(myParam) {
var b = baz();
});
function baz(){
return {/*whatever you want*/};
}
在代码的其他地方:
deferred.resolve(myParam);
在本例中,确保仅在满足某些条件后才调用“baz”。基本上,不是将布尔值设置为true,而是“解析”延迟对象。其他答案已经说明了重要部分:不,这不起作用。我想发布这篇文章,以便提供更多的背景信息,说明为什么这样做行不通 在后台,node.js正在运行一个事件调度循环。有一个事件队列(至少在概念上包括“应用程序启动”、“传入消息”、“套接字连接”、“文件io完成”等)。当事件发生时,事件调度器将事件从队列中拉出,并调用与该事件相关联的任何Javascript函数。回调函数完成后,调度会将下一个事件从队列中拉出来,进行处理,等等。这是完全同步的-在当前事件完成之前,无法处理下一个事件 因此,当您有这样的代码时:
var done = false;
while (!done) {
process.nextTick(function () {
done = true;
});
}
会发生什么?进入while循环后,process.nextTick会将事件放入事件队列中,以便在下次运行事件循环时进行处理。然后,代码在while中循环,检查完成(仍然为false),对另一个事件进行排队,等等
由于在函数返回之前,事件循环无法处理排队的事件,因此事件循环被卡住,process.nextTick的回调永远不会被调用。你确保了永远不会有“下一次”
您不能在纯Javascript代码中执行同步等待。在Node.js中,您可以在C扩展中实现它(这就是fs.readFileSync
之类的东西的实现方式)。您可以使用一些Javascript编译器技巧(如或)来编写看起来同步的代码。但实际上他们都在使用异步回调模式
我的建议是首先学习核心回调模式,以便理解它。当然,这是一种巨大的痛苦。从那里调查承诺(我个人喜欢作为承诺实现,或者如果您使用ES6,您可以使用内置承诺)或许多异步帮助程序库中的一个。这很好,但却是一个可怕的反模式。你永远不应该在节点中等待。有时在节点中“等待”是可以的,当服务器第一次启动时,或者当你运行一个脚本时,该脚本取决于外部进程可能设置的条件,但是o/w是的。因为代码现在在OP中(我不会更改它),它看起来确实在while循环中等待(关于什么我是对的?)我原本以为调用process.nextTick会迫使node.js调用事件循环队列中的下一个函数,但事实并非如此,它只是停留在同一个函数中。谢谢你,是的,我熟悉Q和Bluebird,但除了jQuery风格的promisesJoel之外,我没有太多使用过它们。你可能对Randy的答案感兴趣,它与set一起工作立即。
process
是节点中的全局对象。它在您的浏览器中不存在。:)是的,当然,我忘了,有人请创建一个Node.js fiddle:)有人修复了jsFiddle,因此它会引发错误。我更新了我的答案,将setImmediate
用作进程。nextTick
将被弃用。我测试过了,确实有效。嗯,让我再试一次你作弊了!:)process.nextTick不起作用,但您是对的setImmediate()起作用。如果你能成功地使用process.nextTick,我很想看看它是什么样子@Chris Tavares,Randy确实与setImmediate()一起使用了它;我试着让它工作,但它似乎患有与你在回答中描述的相同的疾病。下面是一个基本上代表Randy的解决方案的JSFIDLE:我调试了它,它永远不会离开wait()函数。setTimeout参数(anon函数)从未被调用,因此bool从未被设置为true。我有一个问题。。本例中的nextTick队列在一段时间后是否将满?然后呢?