1

我尝试使用 node.js,我发现有趣的事情(也许,只是为了我)我写了一些这样的代码:

var flag = false;
doSomethingAsync().on('complete', function(data) {
    console.log('from callback');
    //do somestuff
    flag = true;
});
do{
   // there I want to wait for callback result
}while(!flag);

但我观察到我没有看到回调日志。为什么会这样?我尝试将 do...while 更改为另一个循环,但观察到相同的行为
注意:我知道这对节点中的某些内容是不合适的,但我想了解为什么会发生这种情况

4

3 回答 3

4

Node 实现了一个协作 I/O 循环,仅在程序空闲(不执行任何计算)时才运行是否必须执行 I/O 的检查;协作部分由开发人员实现,不会通过执行阻塞计算来阻塞 I/O 循环。

do-while循环(它本身不包含任何 I/O 操作)的问题在于它阻止程序进入空闲状态,因此有效地阻止了任何 I/O(包括由执行的 I/O)doSomethingAsync的执行。

这可以通过使用来缓解setImmediate(),尽管这不能在do-while循环中使用。

于 2013-07-23T08:47:00.620 回答
3

永远不要这样做,不管是什么语言。

如果您不释放 CPU,您将无法轻松预测引擎将如何处理您启动的其他任务。它可能决定将所有资源都提供给该循环而不让doSomethingAsync任何进展,从而使循环无休止并且永远不会触发回调。

特别是在 nodejs 中,由于只有一个线程来执行您的 javascript 代码(即使这里有其他线程用于 IO),所以在循环结束之前不会启动回调(它不会这样做)。

只需在回调中或从回调中调用的函数中执行您需要的操作:

function goon() {
   // do other stuff
}

doSomethingAsync().on('complete', function(data) {
    console.log('from callback');
    //do somestuff
    goon();
});
于 2013-07-23T08:20:21.503 回答
2

您正在做的事情称为忙等待/循环。它会浪费您的 CPU 处理时间。这在所有语言中都是不好的做法,不仅仅是在节点中。

在节点中真正糟糕的是它锁定了事件循环。在事件循环中,每个事件处理程序都被给予 CPU 处理,它使用它并且必须在最后释放控制。当您运行无限循环时,它会阻止下一个事件的执行,以及事件循环本身。

因此,在您的情况下,标志不能设置为 true,以结束循环。因为循环必须允许标志改变。

var flag = false;
setTimeout(function(data) {
    console.log('from callback');
    flag = true;
},2000);
i=0;
do{
   i +=1;
   console.log(i);
}while(!flag&&i<200);

你的标志只会在循环结束时改变。

看这篇文章

于 2013-07-23T08:56:14.567 回答