我正在编写一些Node.js,我想,来自Java背景,我应该弄清楚如何创建自己的"等待"功能。显然,它会有所不同,因为Java被设计为多线程而Node不是。无论如何,在Node中我想要的功能是我想自己创建一个阻塞函数 - 这样如果程序中的某个布尔值没有设置,我可能想调用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(参数)而不是baz函数(递归地)执行会发生什么?通常,当你想要函数X的返回值,但函数X在返回之前调用自己几次,这是否会造成任何问题?这没什么大不了的,结果是相同的回报价值?我之前已经考虑过这个问题,但从未真正担心或调查过它。
答案 0 :(得分:5)
不要等待'在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);
答案 1 :(得分:5)
其他答案已经说明了重要的部分:不,这不会奏效。我想发布这个内容,以提供更多关于为什么这不起作用的背景信息。
在幕后,node.js正在运行一个事件调度循环。存在一系列事件(包括,至少在概念上,“app start”,“incoming message”,“socket connection”,“file io complete”等)。当事件发生时,事件调度程序将事件从队列中拉出并调用与该事件关联的任何Javascript函数。一旦回调函数完成,调度就会将下一个事件从队列中拉出,处理它等等。这是完全同步的 - 下一个事件在当前事件完成之前无法处理。
所以当你有这样的代码时:
var done = false;
while (!done) {
process.nextTick(function () {
done = true;
});
}
会发生什么?您输入while循环,process.nextTick 将事件放在事件队列中,以便在下次运行事件循环时进行处理。然后您的代码循环返回while,检查完成(仍然为false)排队另一个事件等等。
由于事件循环在函数返回之前无法处理排队事件,因此事件循环会卡住,并且不会调用process.nextTick的回调。你已经确保永远不会有“nextTick”。
您 无法 在纯Javascript代码中执行同步等待。在Node.js中,您可以在C扩展中执行此操作(这就是fs.readFileSync
之类的实现方式)。您可以使用一些Javascript编译器技巧(如streamline或co)来编写看起来同步的代码。但在引擎盖下,他们都使用异步回调模式。
我的建议是首先学习核心回调模式,以便你理解它。这是一种巨大的痛苦。从那里调查promises(我个人喜欢Bluebird作为promise实现,或者如果你使用的是ES6,你可以使用内置的promises)或许多异步帮助库之一。
答案 2 :(得分:1)
在Javascript中执行此操作的典型方法是使用promises。例如,使用“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,而是“解析”延迟对象。