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. I'd like to send this file to the client one line at a time. But my problem is that the server waits until response.end()
has been called to send the whole thing at once.
The code for my server looks like this:
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);
}
I really don't want to make the user wait until the entire JSON file has been loaded before my script can start parsing the results. How can I make my server send the data in chunks?
Additional info: How do I know my Node.js server isn't sending any part of the file until after response.end
has been called?
I'm using XMLHttpRequest
to handle the chunks as they arrive. I understand that http.responseText always grows with each chunk, so I filter through it to find the new lines that arrive each time:
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();
The array previousResults
should grow slowly over time. But instead, there's a huge delay, then everything suddenly appears all at once.
The following thread is related. But unfortunately, none of the proposed solutions solved my problem... Node.js: chunked transfer encoding