非阻塞 I/O 如何与通道一起工作

How non-blocking I/O works with channels

我想知道 node.js 中的引擎如何知道何时调用和执行排队的操作。我理解 node.js 是单线程的,使用异步非阻塞来执行操作。

但是假设您正在从数据库中调用某些东西并且 node.js 将操作排队并且不等待它执行更多代码行。作为单线程,它将数据存储在通道中(如果我没记错的话)。但是服务器如何知道网络不忙并且是执行排队操作的正确时间。

或者在程序末尾执行排队的操作。这不可能。所以我很想知道幕后发生了什么以及节点服务器如何知道何时执行排队的操作。

不清楚您所说的 "channels" 是什么意思,因为它不是内置的 node.js 概念,也不是内部用来描述 node.js 工作原理的术语。您评论中的 tutorial you reference 是在谈论 Java 语言,而不是 Java 脚本语言,因此它与 node.js 完全无关。该教程中 "channels" 的概念是特定 NIO 库在 Java 中实现的。

但是,如果您真的只是想问 node.js 中的异步操作是如何工作的,我可以解释这个一般概念。

node.js 处理事件队列。 node.js 解释器获取事件队列中的下一个事件并执行它(通常涉及调用回调函数)。该回调函数运行(单线程)直到它 returns。当它 returns 时,node.js 解释器然后在事件队列中查找下一个事件。如果有,它会抓住下一个事件并调用与其关联的回调。如果事件队列中当前没有事件,则它等待将事件放入事件队列中(无事可做,期望可能会运行一些垃圾收集)。

现在,当您在 Java 脚本中运行某种异步操作(例如数据库查询)时,您可以使用数据库查询函数启动查询(通过将查询发送到数据库)然后立即 returns。这允许您启动该查询的 Java 脚本然后 return 并将控制权交还给 node.js.

同时,一些本机代码正在管理与您的数据库的连接。当响应从数据库返回时,一个事件被添加到内部 node.js 事件队列。

每当 node.js 解释器完成 运行 其他 Java 脚本时,它会在事件队列中查找并提取下一个事件并调用与之关联的回调。这样,您的数据库查询结果将由您的代码处理。在此处的所有情况下,异步操作都有某种与之关联的回调,当解释器在事件队列中找到事件时可以调用该回调。

Being single thread it stores the data in channels(if I am not wrong).

node.js 没有 "channels" 概念,所以我不确定你的意思。

Or it executes the queued operation at the end of the program.

当结果从数据库返回时,一些本机代码管理会将事件插入 node.js 事件队列。 Java脚本解释器将为该事件提供服务,然后下次它返回事件循环(其他 Java 脚本已完成 运行,是时候检查下一个要处理的事件了) .

了解启动异步操作是非阻塞的很重要,因此您会得到:

console.log("1");
callSomeAsyncFunction(someData, (err, data) => {
    // this callback gets called later when the async operation finishes
    // and node.js gets a chance to process the event that was put
    // in the event queue by the code that managed the async operation
    console.log("2");
});

// right here there is nothing else to do so the interpreter returns back
// to the system, allowing it to process other events
console.log("3");

由于事物的非阻塞性质,这将记录:

1
3
2

关于该主题的一些其他参考资料:

How does JavaScript handle AJAX responses in the background?

Node 在内部使用底层操作系统非阻塞 io API-s。 Linux 见 overlapped io, WSAEventSelect for Windows, select