NodeJS 事件循环的确切处理是什么?

问题描述

我知道 NodeJS 事件循环从事件队列中收集任务并将控制权转移到任务的回调。任务完成后,任务从事件循环中转移控制权。

因此,我认为实际上返回回调是一个从 Task 获得控制权的 Event Loop。

这是正确的想法吗?

另外,如果对于Event Loop中可能发生的阻塞现象的假设是正确的,如果有一个延迟的异步任务,事件循环是否可以在等待任务返回控制权的同时处理其他任务?

>

或者这个假设是错误的,所以事件循环在延迟的异步任务完成之前不起作用?

在 async await 的情况下,我想知道 await 是否停止了 Event Loop。

解决方法

您可以将事件循环视为实际循环,例如:

let event_queue = [compiled_toplevel_code];
while (true) {
  if (event_queue.length === 0) {
    sleepUntilWokenUp();
  }
  if (event_queue.length > 0) {
    let callback = event_queue.shift();
    callback();
  }
}

其中 sleepUntilWokenUp() 是一个特殊的函数,它会挂起当前线程,直到另一个线程发送一些信号来唤醒它。异步操作(如文件系统或网络访问)由此类其他线程处理。当他们有一个回调准备好执行时,他们会将它排入队列,然后发送适当的唤醒信号。

您可以想象 setImmediate(callback) 被实现为 event_queue.push(callback)

从事件循环到回调的“转移控制”仅仅意味着调用回调; “返回控制”到事件循环只是意味着回调函数返回。

长时间运行的“异步”任务总是分解成在主线程上运行的片段,安排一些要完成的工作(通常在另一个线程上),然后返回。一旦请求的任务在后台完成,它们相应的回调就会被排队。即使使用 await 的“同步”调用也只是将函数分成两半的语法糖,这样前半部分运行完成,当等待的任务完成时,后半部分被推送到 event_queue .

现实中的完整情况稍微复杂一些(在 Node 文档中有详细描述),不同种类的事物有几个不同的队列,但以上描述了总体思路。