Javascript node.js:循环回调未按预期工作时

Javascript node.js:循环回调未按预期工作时,javascript,node.js,loops,callback,while-loop,Javascript,Node.js,Loops,Callback,While Loop,知道Node.js异步工作时,编写如下内容: function sleep() { var stop = new Date().getTime(); while(new Date().getTime < stop + 15000) { ; } } sleep(); console.log("done"); 函数睡眠(){ var stop=new Date().getTime(); while(new Date().getTime

知道Node.js异步工作时,编写如下内容:

function sleep() {
    var stop = new Date().getTime();
    while(new Date().getTime < stop + 15000) {
        ;
    }
}

sleep();
console.log("done");
函数睡眠(){
var stop=new Date().getTime();
while(new Date().getTime
…将调用sleep(),在while循环期间(15秒)阻塞服务器,然后在控制台上打印“done”。据我所知,这是因为Node.js只允许JavaScript访问主线程,因此这种绑架行为将停止进一步的执行

因此,我理解解决方案是使用回调:

function sleep(callback) {
    var stop = new Date().getTime();
    while(new Date().getTime() < stop + 15000) {
        ;
    }
    callback();
}

sleep(function() {
    console.log("done sleeping");
});

console.log("DONE");
函数睡眠(回调){
var stop=new Date().getTime();
while(new Date().getTime()
所以我想这会在15秒后打印“完成”由于调用了sleep()函数并向其传递了一个指向回调函数的指针,因此“已完成睡眠”。当此函数工作时(While循环),将执行最后一行(打印“完成”)。15秒后,当sleep()函数完成时,它调用给定的回调函数,然后该函数打印“done sleep”

显然,我理解这里有点不对,因为以上两种方式都会造成阻碍。谁能澄清一下吗

提前感谢,,
Slagjoeyoco

回调与异步不是一回事,它们只是在您想要获得一个。。。回拨。。。从异步操作。在您的情况下,该方法仍然同步执行;节点并不仅仅神奇地检测到有回调和长时间运行的操作,并使其提前返回


真正的解决方案是使用
setTimeout
而不是另一个线程上的忙循环。

您正在立即调用
sleep
,新的
sleep
功能块。它不断迭代,直到满足条件为止。您应该使用
setTimeout()
来避免阻塞:

setTimeout(function () {
    console.log('done sleeping');
}, 15000);

如前所述,异步执行应该通过setTimeout()而不是while来实现,因为while将冻结在一个“执行帧”中

另外,您的示例中似乎存在语法错误


这一个很好用:

Javascript和node.js是单线程的,这意味着一个简单的
,而
是块;在
while
块完成之前,无法处理任何请求/事件。回调并不能神奇地解决这个问题,它们只是帮助将自定义代码传递给函数。相反,使用
process.nextTick
进行迭代,这将在本质上为您提供相同的结果,但也为要处理的请求和事件留出空间,即,它不会阻止:

function doSleep(callback) {
    var stop = new Date().getTime();

    process.nextTick(function() {
        if(new Date().getTime() < stop + 15000) {
            //Done, run callback
            if(typeof callback == "function") {
                callback();
            }
        } else {
            //Not done, keep looping
            process.nextTick(arguments.callee);
        }
    });
}

doSleep(function() {
    console.log("done sleeping");
    console.log("DONE");
});
函数doSleep(回调){
var stop=new Date().getTime();
process.nextTick(函数(){
如果(新日期().getTime()
您正在使自己变得复杂。一个简单的setTimeout(回调,延迟)应该足以产生与异步指令相同的结果。@FabiánH.jr。关键是OP可能有兴趣了解为什么他的
while
不起作用,以及
while
如何以非阻塞方式编写,这是一个比“你的方法不起作用没关系,用另一种方式来做”更好的答案,总的来说,答案很好,现在您提到了node.jsf的内部流程,这是一个很有见地的问题。有趣的是,我知道单独一个while循环会阻止脚本执行其他操作,因为它在一个线程中运行。出于某种原因,我认为节点会识别阻塞代码,如果我用回调调用它,它只会让它工作,并在完成后返回,同时让最后一行执行。当然,这是没有意义的,因为,同样,只有一个线程可以工作,当然,由于node没有“看到”有一个繁忙的循环,它不会将此函数移动到一个单独的线程中,因此主线程会被阻塞。因此process.nextTick会在事件循环的下一个勾号中执行给定的函数,让其他排队的任务,如最后一行应该打印“完成”,在脚本停止15秒循环的下一个滴答声之前执行。所以,假设我们将循环5毫秒,循环之外还有5个其他任务要完成,我猜使用process.nextTick将执行排队的任务#1,然后是5毫秒循环的一个勾号,然后是任务#2,依此类推,对吗?