首页 > 解决方案 > NodeJS 事件循环的确切处理是什么?

问题描述

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

因此,我认为实际上返回回调是一个事件循环,它已经从任务中获得了控制权。

这是正确的想法吗?

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

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

在异步等待的情况下,我想知道等待是否停止事件循环。

标签: javascriptnode.jstypescriptv8libuv

解决方案


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

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();
  }
}

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

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

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

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

现实中的完整情况稍微复杂一些(并在 Node 文档中详细描述),有几个不同的队列用于不同种类的事物,但上面描述了一般的想法。


推荐阅读