【问题标题】:How does nodejs event loop keep running without a for/while forever loop?nodejs 事件循环如何在没有 for/while 永远循环的情况下继续运行?
【发布时间】:2021-07-12 10:33:49
【问题描述】:

我读过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?。那里有不同的意见,例如Bryan Oakley 的回答说是,其他人说不是。

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

【问题讨论】:

    标签: node.js event-loop libuv libev


    【解决方案1】:

    为什么要使用“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
    }
    

    【讨论】:

    • 您好,感谢您回答我的问题。我想我需要稍微改一下我的问题以便更好地讨论。我只是说无限循环,所以我不应该只说 while true。正如你所说的“再次从第一阶段开始”,我只是想知道如何。
    • pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#EXAMPLE_PROGRAM 可能是一个更好的例子,但是 ev_run (loop, 0);永远运行?
    • 我认为更重要的问题是loop (struct ev_loop *loop = EV_DEFAULT;) 是什么,它有什么作用? :) 不幸的是,您的问题太宽泛了,基本上需要解释 libuv 周围的整个生态系统以及它包含的内容。
    • 您可以在这里阅读更多内容:docs.libuv.org/en/v1.x/design.html
    • 您好,请查看github.com/libuv/libuv/blob/v1.x/src/unix/core.c#L369确实有一段时间了
    【解决方案2】:

    有了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 循环,所以我想我只是问了一个愚蠢的问题。

    【讨论】:

    • 请记住,它与您预期的“虽然真实”不同。我昨天读到了一件有趣的事情——它会让偶数循环“在至少有一个活动线程时”保持工作。我认为这就是条件中的r :) 无论如何,这是一个很好的问题,可以理解它的实际工作原理。
    • 对我来说更有趣的问题是迭代是如何发生的——据我所知,uv_run 执行单个事件循环阶段循环。在我看来,这个 while 循环涉及循环必须在此迭代中执行的所有句柄(和回调)。如果我错了,请纠正我:)
    猜你喜欢
    • 1970-01-01
    • 2020-08-10
    • 2015-07-26
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 2014-05-30
    • 2017-06-14
    相关资源
    最近更新 更多