9

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

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

sleep();
console.log("done");

...将调用 sleep(),在 while 循环期间(15 秒)阻塞服务器,然后将“完成”打印到控制台。据我了解,这是因为 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");

所以我认为这会在 15 秒后打印“完成”。'完成睡眠',因为 sleep() 函数被调用并被传递一个指向回调函数的指针。当这个函数工作时(while循环),最后一行将被执行(打印'done')。15 秒后,当 sleep() 函数完成时,它调用给定的回调函数,然后打印“完成睡眠”。

显然我在这里理解了一些错误,因为上述两种方式都阻塞了。有人可以澄清一下吗?

提前致谢, 斯拉格乔约科

4

4 回答 4

14

Javascript 和 node.js 是单线程的,这意味着一个简单的while块;while在块完成之前,不能处理任何请求/事件。回调并不能神奇地解决这个问题,它们只是帮助将自定义代码传递给函数。相反,迭代 using 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");
});
于 2012-10-13T00:34:23.130 回答
9

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

setTimeout(function () {
    console.log('done sleeping');
}, 15000);
于 2012-10-13T00:26:51.767 回答
2

回调与异步不同,它们只是在您想从异步操作中获取...回调时很有帮助。在您的情况下,该方法仍然同步执行;Node 不只是神奇地检测到有回调和长时间运行的操作,并使其提前返回。

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

于 2012-10-13T00:26:35.000 回答
0

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

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

这个工作正常:http: //jsfiddle.net/6TP76/

于 2012-10-13T00:33:24.097 回答