簡體   English   中英

如果node.js是單線程的,那么為什么server.listen()會返回?

[英]If node.js is single threaded then why does server.listen() return?

我熟悉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();

在像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();

Server.listen立即返回,然后按預期陷入繁忙循環。 我的瀏覽器無法連接到服務器,這是預期的。

如果我刪除busy循環並返回原始代碼,一旦console.log('Main completed'); 執行而不是程序退出,主線程跳回到事件循環。

這是如何運作的。 為什么主線程返回后主線程會跳回到服務器代碼中?

編輯:我認為重新解決了主要功能中不存在事件隊列但它在哪里? 擁有什么? 什么時候主函數會參考它運行?

http.createServer(handler)server.listen(port)視為與瀏覽器中的someElement.addEventListener('click', handler)類似。

當您運行someElement.addEventListener('click', handler) ,它會綁定一個事件偵聽器,該事件偵聽器將在someElement上觸發click事件時將handler發送到回調隊列。

http.createServer(handler)server.listen(port) http.createServer(handler)結合使用的方式非常相似。 http.createServer(handler)返回一個eventEmitter ,而server.listen(port)告訴node.js,當在給定端口上收到http請求時,應觸發此事件。 因此,當請求進入時,事件被觸發, handler被推送到回調隊列。

此時,事件循環callstack和回調隊列如何交互只是一個簡單的問題。 callstack是當前正在執行的函數堆棧, 回調隊列是等待執行的回調集合,而事件循環是將回調隊列回調拉出並將它們發送到callstack

因此,從某種意義上說,事件循環是保持一切運行的原因,但是,如果通過在其中一個回調中阻塞callstack使其無法循環,則事件循環永遠不會再次運行並且回調永遠不會被執行,從而導致破碎/反應遲鈍的申請。

這里要理解的基本概念是事件循環和協作(非搶先)多任務模型

那個server.listen調用在下面用事件循環注冊一個回調,並且該回調與每個其他注冊的回調共享主執行線程。

當您拋出忙循環時, server.listen回調永遠不會獲得執行時間(事件引擎也不會),因為系統是非搶占式的 也就是說,沒有回調可以中斷任何其他回調 - 回調必須通過終止將控制權放回到事件循環,因此事件循環將根據它已排隊的事件調用其他已注冊的回調。

基本上http.createServer指針返回到一EventEmitter 您可以將偵聽器等附加到將在發出事件時執行的對象。 這些是在事件循環內部處理的,它是異步運行的,不會阻塞主線程。 結帳的HTTP文檔,了解有關詳細信息, HTTPEventEmitters

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM