node.js 事件队列在哪里?

nbr*_*ing 5 javascript c++ node.js

我在堆栈溢出上看到过类似的问题,但没有一个完全深入探讨我的问题?我熟悉事件队列,它们如何工作以及实现它们。我是 node.js 的新手,我正在尝试了解 Node.js 是如何做到的。

在 C++ 应用程序中,您将执行以下操作:

int main(){
    std::vector<Handler*> handlers;
    BlockingQueue queue = new BlockingQueue();
    //Add all the handlers call constructors and other such initialization

    //Then run the event loop
    while(true){
        Event e = queue.pop();

        for( std::vector<Handler>::iterator it = handlers.begin(); it != handlers.end(); ++it){
            *it.handle(e);
         }
     }
}
Run Code Online (Sandbox Code Playgroud)

现在在 node.js 的情况下,我可能有一个名为 main.js 的主文件,看起来像。

var http = require("http");
function main(){
    // Console will print the message
    console.log('Server running at http://127.0.0.1:8080/');
    var server = http.createServer(function (request, response) {

        // Send the HTTP header
        // HTTP Status: 200 : OK
        // Content Type: text/plain
        response.writeHead(200, {'Content-Type': 'text/plain'});

        // Send the response body as "Hello World"
        response.end('Hello World\n');
    });

    server.listen(8080);
    console.log('Main completed');
}

main();
Run Code Online (Sandbox Code Playgroud)

我知道 server.listen 正在将处理程序附加到事件队列,并且我们正在添加类似于 c++ 示例的回调。

我的问题是。事件队列在哪里?它是在某个地方的 javascript 中还是内置在解释器中?另外,相对于主事件循环,main 函数是如何被调用的?

jfr*_*d00 5

事件队列在哪里?它是在某个地方的 javascript 中还是内置在解释器中?

事件队列内置于承载 Javascript 解释器的操作环境中。它不是 Javascript 本身的基础,因此它不是实际 JS 运行时的一部分。一个有趣的指标是它setTimeout()实际上不是 ECMAScript 的一部分,而是宿主提供给 Javascript 环境的一些东西。

node.js 中围绕 Javascript 实现的系统会跟踪外部触发的事件(计时器、网络结果等),当 Javascript 不忙于执行某事并且发生外部事件时,它会触发关联的 Javascript 回调。如果 Javascript 正忙于执行某事,那么它会将该事件排队,以便一旦 Javascript 不再忙,它就可以触发队列中的下一个事件。

node.js 本身libuv用于事件循环。您可以在此处阅读更多相关信息。它提供了一种多平台方式来执行事件化的异步 I/O,该方式是为 node.js 开发的,但也被其他一些项目使用。

这是一个相关的答案,也可能有帮助:

在节点中等待回调时运行任意代码?

另外,相对于主事件循环,main 函数是如何被调用的?

当 node.js 启动时,它会被赋予一个初始脚本文件来执行。它将该脚本文件加载到内存中,解析其中的 Javascript 并执行它。在您的特定示例中,这将导致函数main被解析,然后将导致执行main()which 将运行该函数。

加载、解析和执行在 node 启动时传递给 node 的脚本文件是 node.js 的任务。它根本与事件队列无关。在某些 node.js 应用程序中,它运行该初始脚本,然后退出(完成其工作)。在其他 node.js 应用程序中,初始脚本启动计时器或服务器或类似的东西,它们将在未来接收事件。在这种情况下,node.js 会运行初始脚本直到完成,但因为现在已经创建了持久对象并正在侦听事件(在您的情况下是服务器),nodejs 不会关闭应用程序。它让它继续运行,以便它可以在这些未来事件发生时接收它们。


这里缺少的一个部分是像您创建的服务器对象这样的东西允许您注册一个回调,当某些特定事件发生时,该回调将在将来被调用一次或多次。此行为未内置于 Javascript 中。相反,实现这些对象或它们使用的 TCP 函数的代码必须维护已注册的回调列表,当这些事件发生时,它必须执行代码,以便调用适当的回调并传递适当的数据。在 的情况下http.createServer(),它是 Javascript 和 nodejs http 库中的本机代码的混合,使其工作。