问题描述
注意:这不是预检选项,也不是网站图标或其他类似的东西.它实际上是 2 个帖子.下面有一个屏幕截图可以更清楚地显示这一点.
我的规格/版本:
- macOS Sierra 版本 10.12.3
- Chrome 版本 61.0.3128.0(官方构建)开发版(64 位)
- 节点 v8.0.0
我有一个使用 setTimeout 等待 10 秒再响应的服务器.我有一个前端,可以向服务器发送一个 POST.使用wireshark,我可以看到浏览器实际上做了2个POST,第二个在t+5s.服务器看到这两个 POST 并响应两者.前端只获取第二个 POST 的结果.
I have a server that uses setTimeout to wait 10 seconds before responding. I have a frontend that makes a single POST to the server. Using wireshark I'm able to see that the browser actually makes 2 POSTs, a second one at t+5s. The server sees both these POSTs and responds to both. The frontend only gets the result of the second POST.
在下面的示例中,您将看到获取实际上需要 15 秒才能完成,而不是您期望的服务器超时时间为 10 秒.
In the example below you will see that the fetch actually takes 15 seconds to complete, rather than the 10 seconds you'd expect from the timeout in the server.
调用是 CORS,仅在服务器响应时间超过 5 秒时才会发生.
The call is CORS, and only happens when the server takes longer than 5 seconds to respond.
这里发生了什么,我该如何阻止它?
What is going on here and how can I stop it?
这是一个最小的复制:
server.js(使用节点运行)
server.js (run this with node)
var http = require("http");
// A counter for the requests
var counter = 0;
var server = http.createServer(function(request, response) {
// Closure to prevent the request number from changing with the counter.
(function(requestNumber) {
console.log('Incoming:', request.method, "assigning number", requestNumber);
// CORS headers
response.writeHead(200, {
"Content-Type": "application/json",
"Access-Control-Allow-Methods": "GET,HEAD,PUT,POST,DELETE",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "authorization,content-type,expect",
});
// Respond to options immediately.
if (request.method === "OPTIONS") {
response.end()
} else {
// Otherwise simulate a long running process (db write whatever)
setTimeout(function() {
console.log('Timeout done, responding to request number', requestNumber);
response.write(JSON.stringify({ number: requestNumber }));
response.end();
}, 10000);
}
}(counter++));
});
server.listen(8080);
console.log("Server is listening");
在前端获取调用:
var start = new Date();
console.log('making call. Wait ~15 seconds for the result to come back');
fetch('http://localhost:8080', {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
method: 'post',
mode: 'cors',
body: JSON.stringify({ some: 'content' }),
}).then(result => result.json()).then(json => {
console.log('result', json);
console.log('call took:', (new Date() - start), 'seconds');
}).catch(err => {
console.log('err', err);
});
这是服务器、前端控制台和wireshark流量的截图:
Here is a screenshot of the server, the frontend console and the wireshark traffic:
这里是网络标签.您可以看到请求停滞"了 5 秒钟.
And here is the network tab. You can see the request is 'stalled' for 5 seconds.
我所做的测试中的一些额外说明:
Some additional notes from testing I've done:
这发生在 chrome 和 firefox 中,但不是 safari.(我在 Mac 上,chrome 版本 60.0.3112.20(官方构建)开发(64 位))这可能只发生在 CORS 上,但无法通过最小的测试用例进行确认.我用 jQuery 的 ajax
尝试了它,看看它是否可能与 fetch 相关,但它仍然发生了.(我将检查 jQuery 源代码,看看它是否仍在使用 xhr,因为我实际上不确定它是否还没有移到 fetch 上.)
This happens in chrome and firefox, but not safari. (I am on a mac, chrome Version 60.0.3112.20 (Official Build) dev (64-bit)) It's possible that this only happens with CORS, but haven't been able to confirm with a minimal test case. I tried it with jQuery's ajax
to see if it was maybe fetch related but it still happened. (I will check the jQuery source to see if it's still using xhr under the hood because I'm not actually sure that it hasn't moved over to fetch.)
推荐答案
原来这是 Node 8.0.0 的一个错误,并已被 8.1.1 修复.
So it turns out this was a bug with Node 8.0.0 and has been fixed by 8.1.1.
我还没有确定确切的错误,但它可能是其中之一:
I haven't nailed down the exact bug but it could be one of these:
https://github.com/nodejs/node/pull/13549
https://github.com/nodejs/node/commit/2cb6f2b281
这篇关于Chrome/Firefox 在引擎盖下发送两个 POST,间隔正好 5 秒,只调用一次来获取 Nodejs 8.0.0 服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!