在 node.js 中,它在单个线程中运行您的 Javascript(假设我们不是在谈论工作线程或集群)。但是,node.js 内置库中的许多异步操作(例如文件 I/O 或一些加密操作)使用它们自己的线程来完成它们的任务。因此,当您调用异步操作(例如fs.open()
打开文件)时,它会转换为本地代码,从内部线程池中获取一个线程,然后该线程开始打开文件。这fs.open()
然后函数返回到您的Javascript(而线程在后台继续)。稍后,当它完成任务时,内部线程将一个事件插入到 nodejs 事件队列中,当 nodejs 有循环检查事件队列时,它会找到该事件并运行与之关联的 Javascript 回调以将异步结果返回给你的 Javascript。
因此,即使可能涉及线程,您的 Javascript 仍然是通过事件循环的单线程。
因此,nodejs 确实使用原生代码线程进行一些内部原生代码操作。网络和计时器等其他东西是在没有线程的情况下实现的。
那么如果我在 Node 中发送一个从数据库中获取数据的请求,Event Demultiplexer 是如何处理它的呢?主线程是否停止事件循环以处理该操作,然后在事件处理程序排队后恢复?
这些术语如“事件多路复用器”是您应用于 node.js 的东西。它们根本不是 node.js 使用的东西,所以我不完全确定你在问什么。
Node.js 一次运行一个事件。它没有中断驱动的能力。因此,它会运行一个事件,直到该事件将控制权返回给事件循环(通过return
从启动一切的回调中发出 a )。现在,原始事件可能不完整——它可能正在做一些异步的事情,会触发另一个事件来宣布完成,但它现在已经完成了 Javascript 的运行并将控制权返回给事件循环。
当传入的 Fetch 请求(只是传入的 http 请求)到达服务器时,它首先由操作系统排队。然后,当事件循环有机会看到它时,它会被添加到 node.js 事件队列中,并在它之前的其他事件完成处理时以 FIFO 顺序提供服务。现在,nodejs 事件循环并不像单个事件队列那么简单。它实际上有几个不同的队列用于不同类型的工作,并且对首先运行的内容具有优先级,但在最简单的级别上,您可以开始将其视为单个 FIFO 队列。而且,没有任何事情被打断。
从事件队列中拉出一个事件,运行与之关联的 Javascript 回调。当该回调返回事件循环时,获取下一个事件并执行相同操作。
事件可以通过本机代码线程(例如可能通过文件 I/O 或某些加密操作完成)或通过作为事件循环周期的一部分内置在事件循环中的某些轮询机制添加到事件队列中,它会检查某些事情准备好运行(与网络和计时器一样)。