我想知道即使回调已经完成。如果 Node 是单线程模型,主线程上的回调和其他进程如何并行执行。
最佳答案
首先,回调不是并行执行的。一次只有一个 Javascript 执行线程,因此 Javascript 代码不存在实际的并行执行。您可以同时进行多个异步 native 代码操作,但是当它们需要运行某种 Javascript 完成回调时,这些操作一次运行一个,而不是并行运行。
Javascript 是一种事件驱动语言,这意味着计时器、异步磁盘 I/O 回调、网络操作回调等......都使用事件队列。当 JS 引擎完成执行一段 Javascript 并将控制权返回给系统时,JS 引擎会从事件队列中取出下一个事件并执行它。 native 代码操作可以通过将事件插入事件队列来表明它们已完成并希望运行回调。
对于像 HTTP 请求这样的异步操作,例如 http.get()
,基本上会发生以下情况:
- 您的 JavaScript 调用
http.get()
- 该调用发送 http 请求,然后立即返回。无论您传递给
http.get()
的回调是什么,都由 http 模块内部存储,并与特定的网络请求关联。 http.get()
之后的 JavaScript 代码将继续执行,直到完成并将控制权返回给系统。- 然后,一段时间后,上一个 HTTP 请求的响应返回到 TCP 引擎。这会导致 http 模块在 Javascript 事件队列中插入一个事件,以调用您之前使用
http.get()
发送的完成回调。 - 如果 Javascript 引擎当前没有执行任何其他操作,则会执行您的回调并传递结果响应数据。
- 如果 Javascript 引擎此时正在执行某些操作,则该事件将位于事件队列中,直到当前正在执行的 Javascript 片段完成并将控制权返回给系统。此时,JS 引擎会检查事件队列,并将下一个事件从队列中拉出并执行。如果这是您的回调,那么您的回调将在此时被调用。
因此,各种操作(例如异步磁盘 I/O、网络操作等)可以在后台运行,因为它们是由 native 代码(而不是 Javascript 引擎)控制的。如果需要, native 代码能够使用线程。 fs
模块使用线程,而 net
模块则不使用线程,因为 native 操作系统已经支持异步网络操作。
关于node.js - Node.js 中单线程如何处理异步代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41738661/