【问题标题】:Where is the node.js event queue?node.js 事件队列在哪里?
【发布时间】:2015-11-04 00:53:15
【问题描述】:

我在堆栈溢出方面看到过类似的问题,但没有一个完全深入到我的问题中?我熟悉事件队列,它们如何工作以及实现它们。我是 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);
         }
     }
}

现在对于 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();

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

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

【问题讨论】:

  • 事件队列是内置的。它在事件发生时将事件推送到同样内置的调用堆栈上。在当前调用完成之前,不会调用调用堆栈上的调用。

标签: javascript c++ node.js


【解决方案1】:

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

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

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

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

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

Run Arbitrary Code While Waiting For Callback in Node?

还有如何相对于主事件调用主函数 循环?

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

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


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

【讨论】:

  • 运行环境是指节点解释器吗?如果是这样的话。我的 main 函数是在解释器跳转到事件处理之前被调用还是作为事件执行?
  • Node.js 中的原生事件循环基于 libuv en.wikipedia.org/wiki/Libuv
  • @nbroeking - “操作环境”是实际解释器周围的代码集,而不是 Javascript 解释器本身 - 在这种情况下,解释器是 V8 引擎,解释器周围的代码是什么节点.js 添加到 V8 之外。请参阅我最近添加到您其他问题的答案中的其他内容。
  • 您的主脚本将在事件循环启动后被调用。
猜你喜欢
  • 2014-03-09
  • 2013-04-19
  • 1970-01-01
  • 2023-03-07
  • 2023-03-23
  • 2017-01-11
  • 1970-01-01
  • 1970-01-01
  • 2013-05-04
相关资源
最近更新 更多