nodejs 事件循环如何在没有 for/while 永远循环的情况下继续运行?

问题描述

我阅读了Nodejs Event Loop"Event Loop Explained"Don't Block the Event Loop

我认为 nodejs 代码(js 或 c++)中没有 for/while 永远循环,例如正如这里解释了 libev 事件循环 http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#EXAMPLE_PROGRAM

int
   main (void)
   {
     // use the default event loop unless you have special needs
     struct ev_loop *loop = EV_DEFAULT;

    // init

    // Now wait for events to arrive
    ev_run (loop,0);

    // break was called,so exit
    return 0;
 }

那么 nodejs 事件循环如何永远运行,或者确实存在 for/while 永远循环,如 https://en.wikipedia.org/wiki/Event_loop代码所示?

搜索了所有 SO 网站并找到了 Is an event loop just a for/while loop with optimized polling?。那里有不同的意见,例如布莱恩奥克利的回答是肯定的,其他人说不是。

但我的问题与那个有点不同。我想知道没有 for/while 循环,nodejs 事件循环如何继续运行?

解决方法

为什么要使用“while true”循环?尽管人们常说“这是一个无限循环”,但这并不意味着它实际上是一个 while 循环。

正如您在“事件循环解释”中所读到的,事件循环周期有不同的阶段。完成最后一个阶段后,它基本上会自己休眠一小段时间,然后再次从第一阶段开始。众所周知,在浏览器中,使用 setTimeout(callback,0) 实际上在 4 or more 毫秒内执行,这意味着至少有 4ms 的周期间隔。

我认为您在这里最大的误解是过于字面化。 Bryan 说“从概念的角度来看,所有事件循环本质上都是”,这并不意味着那里有实际的 while 循环。它更复杂,并使用操作系统内部调度(内核)来等待一段时间。我想说一个更好的例子(离实际实现还有很远的距离)是:

startEventLoopPhaseExecution() {
  processEventLoopPhases();
  restABit(); // synchronously do nothing for some time
  startEventLoopPhaseExecution(); // start from phase 1 again
}
,

有了Andrey的输入和这篇文章Event loop in JavaScript我进一步查了一下libuv的源码,​​确实是while循环,

https://github.com/libuv/libuv/blob/v1.x/src/unix/core.c#L369

int uv_run(uv_loop_t* loop,uv_run_mode mode) {
 ...
  r = uv__loop_alive(loop);
  if (!r)
    uv__update_time(loop);

  while (r != 0 && loop->stop_flag == 0) {

https://github.com/libuv/libuv/blob/v1.x/src/win/core.c#L596基本一样

int uv_run(uv_loop_t *loop,uv_run_mode mode) {
   ...
   while (r != 0 && loop->stop_flag == 0) {

一开始我很困惑 nodejs 是使用 libev 还是 libuv 中实现的事件循环,但这是另一个话题。

我检查了 ev_run https://github.com/enki/libev/blob/master/ev.c#L3547 的 libev 源代码

这也是一个 do while 循环,所以我想我只是问了一个愚蠢的问题。