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

Ale*_*lls 2 javascript recursion node.js

我正在编写一些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);
Run Code Online (Sandbox Code Playgroud)

所以这个问题有两个方面:

(1)这是在Node.js中实现等待类型功能的最佳方法吗?

(2)如果我调用baz(参数)而不是baz函数(递归地)在执行方面会发生什么?通常,当你想要函数X的返回值,但函数X在返回之前调用自己几次,这是否会造成任何问题?这没什么大不了的,结果是相同的回报价值?我以前考虑过这个问题,但从未真正担心或调查过它.

Ran*_*ndy 6

不要在Node.j中'等待'."等待"阻止所有其他执行.这是一个重要的注意事项,因为如果你阻止,那么布尔值永远不能设置改变.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);
Run Code Online (Sandbox Code Playgroud)


Chr*_*res 6

其他答案已经说明了重要的部分:不,这不会奏效.我想发布这个内容,以提供更多关于为什么这不起作用的背景知识.

在幕后,node.js正在运行一个事件调度循环.存在一系列事件(包括,至少在概念上,"app start","incoming message","socket connection","file io complete"等).当事件发生时,事件调度程序将事件从队列中拉出并调用与该事件关联的任何Javascript函数.一旦回调函数完成,调度就会将下一个事件从队列中拉出,处理它等等.这是完全同步的 - 下一个事件在当前事件完成之前无法处理.

所以当你有这样的代码时:

var done = false;
while (!done) {
    process.nextTick(function () {
       done = true;
    });
}
Run Code Online (Sandbox Code Playgroud)

怎么了?您输入while循环,process.nextTick 将事件放在事件队列上,以便在下次运行事件循环时进行处理.然后你的代码循环回来,检查完成(仍为假),排队另一个事件等.

由于事件循环在函数返回之前无法处理排队事件,因此事件循环会卡住,并且不会调用process.nextTick的回调.你确保从未有过"nextTick".

无法在纯Javascript代码中执行同步等待.在Node.js中,您可以在C扩展中执行此操作(这fs.readFileSync就是实现类似的东西).您可以使用一些Javascript编译器技巧(如streamlineco)来编写看起来同步的代码.但在引擎盖下,他们都使用异步回调模式.

我的建议是首先学习核心回调模式,以便你理解它.这是一种巨大的痛苦.从那里调查承诺(我个人喜欢Bluebird作为承诺实现,或者如果你使用ES6,你可以使用内置的promises)或许多异步帮助库之一.