簡體   English   中英

Node.js:如何使用 http.createServer 獲取 stream 數據

[英]Node.js: How to stream data using http.createServer

I'm using a simple Node.js server to send a large JSON file to the client, where each line has a self-contained JSON object. 我想一次一行地將此文件發送給客戶端。 但我的問題是服務器一直等到response.end()被調用以立即發送整個內容。

我的服務器的代碼如下所示:

http.createServer(async function (request, response) {
   response.writeHead(200, {"Content-Type": "application/json; charset=UTF-8", "Transfer-Encoding": "chunked", "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": 0});
   response.write(JSON.stringify('["The first bit of JSON content"]\n'));
   response.write(await thisFunctionTakesForever());
   response(end);
}

我真的不想讓用戶等到整個 JSON 文件加載完畢后,我的腳本才能開始解析結果。 如何讓我的服務器分塊發送數據?


附加信息:我怎么知道我的 Node.js 服務器在調用response.end之后才發送文件的任何部分?

我正在使用XMLHttpRequest在塊到達時對其進行處理。 我知道 http.responseText 總是隨着每個塊增長,所以我過濾它以找到每次到達的新行:

let http = new XMLHttpRequest();
http.open('GET', url, true);
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() {
    if(http.readyState >= 3 && http.status == 200) {
        // Parse the data as it arrives, throwing out the ones we've already received
        // Only returning the new ones
        let json = http.responseText.trim().split(/[\n\r]+/g)
        let dataChunks = json.map(e => JSON.parse(e));

        let newResults = [];
        for(let i=0; i<dataChunks.length; i++)
        {
            if(!previousResults.map(e => e[0]).includes(dataChunks[i][0]))
            {
                newResults.push(dataChunks[i]);
            }
        }
        previousResults = previousResults.concat(newResults);
    }
}
http.send();

數組previousResults應該隨着時間緩慢增長。 但是相反,有一個巨大的延遲,然后一切突然出現。

以下線程是相關的。 但不幸的是,提出的解決方案都沒有解決我的問題...... Node.js:分塊傳輸編碼

我看到您正在使用分塊編碼: "Transfer-Encoding": "chunked" 這種編碼類型將單獨傳輸每個塊。 真的可以立即寫入每個塊而無需等待其他塊。

每個塊將使用http庫在RFC 2612中定義的格式進行封裝。 通常,每個塊在<CR>, <LF>之后都有一行指示塊大小。 然后你可以發送塊內容。 最后一個塊是一個異常,表示所有塊都完成了。

我可以在下面給你一個例子:

 const http = require("http") function generateChunk(index, res, total) { setTimeout(() => { res.write(`<p> chunk ${index}</p>`) if (index === total) { res.end() } }, index * 1000) } function handlerRequest(req, res) { res.setHeader("Content-Type", "text/html; charset=UTF-8") res.setHeader("Transfer-Encoding", "chunked") let index = 0 const total = 5 while (index <= total) { generateChunk(index, res, total) index++ } } const server = http.createServer(handlerRequest) server.listen(3000) console.log("server started at http://localhost:3000")%

如果您捕獲 TCP 數據包,您將在不同的 TCP 數據包中看到不同的塊。 他們沒有任何依賴。

在此處輸入圖像描述

看圖片:

  1. 每個 PSH 數據包執行一個塊。
  2. 每個塊傳輸之間存在延遲。

但是,HTTP 客戶端(如瀏覽器)在將它們交給應用程序之前必須接受所有塊,原因是:一旦接收到所有塊,服務器也可以發送一些標頭 -尾標 這些標頭包括Content-MD5Content-Length等。一旦收到所有塊,客戶端必須像Content-MD5一樣進行驗證,然后再將它們交給應用程序。 我認為這就是為什么您無法在瀏覽器端一一接收塊的原因。

暫無
暫無

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

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