Chrome为何会「隐秘」重试请求?如何阻止该行为?
Chrome为何会「隐秘」重试请求?如何阻止该行为?
这个问题我之前也碰到过,其实这是Chrome(以及基于Chromium内核的浏览器)的私有自动重试机制,完全不属于JavaScript标准或者Fetch API的规范要求,其他浏览器比如Firefox大概率不会有同样的表现。
为什么会触发“隐秘”重试?
Chrome会针对幂等请求(比如GET、HEAD这类不会修改服务器状态的请求),在遇到连接级意外错误时自动重试——比如你代码里主动调用res.connection.destroy()断开连接,浏览器会认为这是一个非预期的连接中断,而非明确的HTTP错误响应(比如500、404),所以会在后台悄悄发起重试,而且这些重试请求不会在网络面板中单独显示,只会在最后一次重试失败后,在控制台抛出一次“Failed to fetch”错误。
这就是你看到服务器打印三次hello,但浏览器端只显示一个请求记录和一次错误的原因。
如何阻止这个行为?
有几个实用的方法可以避免这种隐重重试:
- 返回明确的HTTP错误状态码:把服务器里的
res.connection.destroy()改成返回一个标准的错误响应,比如:
这样浏览器收到明确的错误状态后,就不会认为是意外连接中断,也就不会重试了。res.status(500).send('Server Error') - 改用非幂等请求:如果业务允许,把请求从GET改成POST(或者其他非幂等的HTTP方法),Chrome不会对非幂等请求进行自动重试,避免重复操作带来的副作用。
- 添加特定响应头:可以在服务器返回的响应中添加
Cache-Control: no-store或者Retry-After头,部分场景下可以抑制浏览器的重试逻辑,但最可靠的还是前两种方法。
额外说明
如果你想验证重试的存在,可以在服务器代码里打印请求的唯一标识(比如req.headers['user-agent']结合时间戳,或者生成一个请求ID),会发现每次重试的请求都是独立发起的,只是浏览器没有在网络面板中暴露这些细节。
备注:内容来源于stack exchange,提问作者callum
相关产品推荐
相关产品推荐

