[英]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 數據包中看到不同的塊。 他們沒有任何依賴。
看圖片:
但是,HTTP 客戶端(如瀏覽器)在將它們交給應用程序之前必須接受所有塊,原因是:一旦接收到所有塊,服務器也可以發送一些標頭 -尾標。 這些標頭包括Content-MD5
、 Content-Length
等。一旦收到所有塊,客戶端必須像Content-MD5
一樣進行驗證,然后再將它們交給應用程序。 我認為這就是為什么您無法在瀏覽器端一一接收塊的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.