Javascript 使用process.nextTick或setImmediate-node.js创建等待函数

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(); }

我正在编写一些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(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队列在一段时间后是否将满?然后呢?