Node.js 给出不同超时的不同 HTTP 响应

Node.js is giving different HTTP responses with different timeouts

我正在使用 Node.js 作为后端(我只是用 localhost 测试它),我注意到这段代码...

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

...第二个 response.end() 调用“覆盖”了第一个(html 页面从未显示)。


所以我决定使用 setTimeout 看看我是否可以先显示 index.html 的内容,然后在几秒钟后显示 application/json 响应...

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

...但是在第一个 response.end() 调用后,我再也看不到 json 出现了。


然后我有了一个奇怪的想法,我决定把超时时间从1000ms改成1ms,然后html的内容就再也不显示了,我马上(或者可能在1ms,就是这么少的时间)看到了json的内容。

我尝试使用 10ms,但它与 1000ms 一样有效,然后我尝试使用 2ms,刷新页面有时显示 json,有时显示 html.


这怎么可能? response.end() 函数不会等到 response 结束?是不是其他原因引起的?提前谢谢你。

当您使用 setTimeout 时,超时的代码会被推送到执行堆栈的“末尾”,然后恢复正常的程序执行。

在这种情况下,发送响应以及如果您直接删除那里的代码将会发生的一切。

我认为您说的 response.end() 不会等到文件传输实际结束。

我实际上在使用 express 时了解到: 如果您在同一函数中执行 response.sendFile(...) 后跟 response.end(),则不会发送实际文件(在实际发送文件之前响应为 'closed'),它只会给出空响应.


编辑:

在您的第一个代码中,JSON 写入总是比 readFile 回调执行得早。 (readFile 回调具有 asynchronous 行为。)


但是一旦超时,“超时回调”和“readFile 回调”之间就会发生竞争。

由于文件加载时间可能会有所不同,因此有时可能比超时时间更快,有时更慢。但是无论哪个回调'wins the race',它都会调用response.end()阻止另一个回调发送任何东西