如果node.js是单线程的,那么为什么server.listen()会返回?

nbr*_*ing 5 node.js

我熟悉c ++和java中基于事件的系统.我试图学习node.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); //Why is this not blocking
    console.log('Main completed');

    //main loop here prevents other stuff from working
}

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

在像java或c这样的语言中我会期待两件事.server.listen都提供了一个事件循环,它会导致server.listen永远不会返回.或者server.listen生成一个新线程并在新线程中立即运行事件循环.然后它将调用console.log,然后返回并关闭该程序.

为了测试这个,我还在console.log下面添加了一个繁忙的循环.

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); //Why is this not blocking
    console.log('Main completed');

    while(true){
        console.log('hi');
    }
}

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

Server.listen立即返回,然后按预期陷入繁忙循环.我的浏览器无法连接到服务器,这是预期的.

如果我删除busy循环并返回原始代码,一旦console.log('Main completed'); 执行而不是程序退出,主线程跳回到事件循环.

这是如何运作的.为什么主线程返回后主线程会跳回到服务器代码中?

编辑:我认为重新解决了主要功能中不存在事件队列但它在哪里?拥有什么?什么时候主函数会参考它运行?

use*_*654 5

想想http.createServer(handler)并且在浏览器中server.listen(port)有点类似someElement.addEventListener('click', handler).

运行时someElement.addEventListener('click', handler),它会绑定一个事件侦听器,该事件侦听器将handler在触发click事件时发送到回调队列someElement.

http.createServer(handler)server.listen(port)以非常相似的方式结合工作.http.createServer(handler)返回一个eventEmitter,并server.listen(port)告诉node.js当在给定端口上收到http请求时,应该触发此事件.因此,当请求进入时,事件被触发,并handler被推送到回调队列.

此时,事件循环callstack和回调队列如何交互只是一个简单的问题.该调用堆栈是函数当前执行的栈,该回调队列是回调等待执行的集合,而事件循环就是回调拉断的回调队列,并把它们发送到调用堆栈.

因此,从某种意义上说,事件循环是保持一切运行的原因,但是,如果通过在其中一个回调中阻塞callstack使其无法循环,则事件循环永远不会再次运行并且回调永远不会被执行,从而导致破碎/反应迟钝的申请.