真的很简单。在内部,node.js包含以下类型的循环:
- 从事件队列中获取一些东西
- 运行指示的任何任务并运行直到返回
- 完成上述任务后,从事件队列中获取下一项
- 运行指示的任何任务并运行直到返回
- 反复冲洗,起泡,重复
如果在某个时刻事件队列中什么都没有,则进入睡眠状态直到事件队列中放置了某些东西。
因此,如果一段Javascript处于
while()循环中,则该任务没有完成,并且按照上述顺序,在完成之前的任务之前,不会从事件队列中挑出任何新东西。因此,一个很长甚至永远运行的
while()循环只会加重工作量。因为Javascript一次仅运行一个任务(用于JS执行的单线程),所以如果一个任务在while循环中旋转,那么其他任何事情都将无法执行。
这是一个简单的示例,可能有助于解释它:
var done = false; // set a timer for 1 second from now to set done to true setTimeout(function() { done = true; }, 1000); // spin wait for the done value to change while (!done) { } console.log("finally, the done value changed!");从逻辑上讲,有些人可能会认为while循环将旋转直到计时器触发,然后计时器将更改
doneto
的值,
true然后while循环将完成,最后的while
console.log()将执行。那不会发生。实际上,这将是一个无限循环,并且该
console.log()语句将永远不会执行。
问题是,一旦您进入
while()循环等待循环,就无法再执行其他Javascript。因此,想要更改变量值的计时器
done无法执行。因此,while循环条件永远不会改变,因此它是一个无限循环。
这是JS引擎内部发生的事情:
done
变量初始化为false
setTimeout()
从现在开始安排1秒的计时器事件- while循环开始旋转
- 在while循环旋转1秒后,计时器会在内部触发JS引擎,并将计时器回调添加到事件队列中。这可能发生在JS引擎内部的其他线程上。
- while循环保持旋转,因为
done
变量永不改变。因为它继续旋转,所以JS引擎永远不会完成该执行线程,也永远不会从事件队列中提取下一项。
node.js is an event driven environment. To solve this problem in a real world
application, the
doneflag would get changed on some future event. So,
rather than a spinning
whileloop, you would register an event handler for
some relevant event in the future and do your work there. In the absolute
worst case, you could set a recurring timer and “poll” to check the flag ever
so often, but in nearly every single case, you can register an event handler
for the actual event that will cause the
doneflag to change and do your
work in that. Properly designed pre that knows other pre wants to know when
something has changed may even offer its own event listener and its own
notification events that one can register an interest in or even just a simple
callback.



