Home > Software engineering >  Node.js is giving different HTTP responses with different timeouts
Node.js is giving different HTTP responses with different timeouts

Time:04-05

I'm using Node.js for backend (I'm just testing it with localhost), and I noticed that with this code...

response.writeHead(200, { 'Content-Type': 'text/html' });
fs.readFile('index.html', (_err, data) => {
    response.end(data);
});


response.writeHead(200, {'Content-Type': 'application/json'})
const responseBody = { headers, method, url, body };
response.write(JSON.stringify(responseBody));
response.end();

...the second response.end() call was "overwriting" the first one (the html page was never shown).


So I decided to use setTimeout to see if I could make appear the content of index.html first, and then after a few seconds the application/json response...

setTimeout(() => {
    response.writeHead(200, {'Content-Type': 'application/json'})
    const responseBody = { headers, method, url, body };
    response.write(JSON.stringify(responseBody));
    response.end();
}, 1000);

...but after the first response.end() call I could never see the json appear.


Then I had a strange idea, I decided to change the timeout from 1000ms to 1ms, and the html content was never shown, I immediately (or maybe after 1ms, which is such a small amount of time) saw the json content.

I tried with 10ms but it worked as with 1000ms, then I tried with 2ms, and refreshing the page it sometimes showed json and sometimes html.


How is this possible? The response.end() function doesn't wait until the response has ended? Is it caused by something else? Thank you in advance.

CodePudding user response:

I think you're correct in saying that response.end() does not wait until file transfer is actually ended.

I actually learned that while using express: If you do response.sendFile(...) followed by response.end() in the same function, then no actual file is sent (the response is 'closed' before the file can actually be sent), it just gives an empty response.


Edit:

In your first code, the JSON writing is always executed earlier than the readFile callback. (The readFile callback is having an asynchronous behavior.)


But once you have the timeout, there is a race between the "timeout callback" and "readFile callback".

Since file loading times can vary, it may be sometimes faster than the timeout and sometimes slower. But whichever callback 'wins the race', it will call the response.end(), preventing the other one from sending anything.

CodePudding user response:

When you use setTimeout, the code you're timing out, is pushed to the "end" of the execution stack, and normal program execution resumes.

In this case sending the response and everything that would happen if you'd straight out delete the code there.

  • Related