【问题标题】:Prevent duplicate HTTP requests for cachable responses防止对可缓存响应的重复 HTTP 请求
【发布时间】:2020-09-11 22:42:02
【问题描述】:

是否有可能(没有请求的应用层缓存)在可缓存的情况下防止多次发送对同一资源的 HTTP 请求?如果是,如何?

例如而不是

at time 0: GET /data (request#1)
at time 1: GET /data (request#2)
at time 2: received response#1 for request#1 // headers indicate that the response can be cached
at time 3: received response#2 for request#2 // headers indicate that the response can be cached

 

at time 0: GET /data (request#1)
at time 1: GET /data (will wait for the response of request#1)
at time 2: received response#1 for request#1 // headers indicate that the response can be cached
at time 3: returns response#1 for request#2

这要求它可以在读取响应标头之前向浏览器指示响应是可缓存的。请问有没有这样的机制。例如。带有前面的 OPTIONS 或某种 HEAD 请求。

【问题讨论】:

  • 我认为你说的“你能在发送之前知道 HTTP 响应是可缓存的吗”,不。还有,你为什么会想要这个?
  • 我在问,我能否向浏览器表明响应是可缓存的。或者我可以请求只让浏览器知道响应是可缓存的。例如。一个 HEAD 请求。
  • 你的初始响应可以设置一些cache headers来告诉浏览器它应该使用这个响应而不是每次都请求一个新的
  • HTTP HEAD 方法请求将返回的标头,如果 HEAD 请求的 URL 是使用 HTTP GET 方法请求的。 Source
  • 所以是的,那么“HTTP HEAD 方法请求将返回的标头,如果 HEAD 请求的 URL 是使用 HTTP 请求的”,缓存控制标头位于标头中,因此它们将被包含在内。我猜浏览器不倾向于这样做,因为它效率低下。提出一个请求比提出两个请求更有效。我不是该请求的负责人,所以我猜测(我已经使用 HTTP 15 年了)它很少使用

标签: javascript http http-headers http2 http-head


【解决方案1】:

我的问题是,如果有一种机制可以向浏览器发出 URI 响应可以缓存的信号

是的,这就是 Cache-control 标头的作用。

以及对该 URI 的任何后续请求都可以返回任何正在进行的请求的响应......理想情况下,这将是 HTTP 规范的一部分

没有 HTTP 不会为您执行此操作,您需要自己实现缓存。这就是浏览器所做的。

我确实想检查一下是否有现成的东西

Javascript 库通常不支持缓存,因为 AJAX 请求通常是针对数据的,并且任何数据缓存通常发生在服务器上。我不知道任何图书馆,当然asking for Js libraries is out of scope on SO。

【讨论】:

  • 当客户端发起 GET 时发起了该资源的 http 推送但尚未完成时,是否会导致推送和 GET 一样,或者浏览器会等待完成推送?另一个选项但同样的问题是使用预加载标签。
【解决方案2】:

根据浏览器的不同,如果可以缓存,第二个请求可能会被停止并提供服务,例如在 Chromium 中用于非范围请求:

缓存实现了单个写入器 - 多个读取器锁定,因此在任何给定时间只有一个对同一资源的网络请求在进行中。 https://www.chromium.org/developers/design-documents/network-stack/http-cache

这里是三个并发请求仅导致单个服务器调用的示例:

fetch('/data.json').then(async r => console.log(await r.json()));
fetch('/data.json').then(async r => console.log(await r.json()));;
setTimeout(() => fetch('/data.json').then(async r => console.log(await r.json())), 2000);

后续请求转0B,随机数相同,表示只调用了一次服务器。

这种行为是不一样的,例如火狐:

想到的interesting question 是当对资源的请求在之前启动但尚未完成的对该资源的 H2 推送时会发生什么。

为了在此处重现测试代码: https://gist.github.com/nickrussler/cd74ac1c07884938b205556030414d34

【讨论】:

    猜你喜欢
    • 2011-02-11
    • 2012-09-29
    • 1970-01-01
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    • 2014-11-23
    • 1970-01-01
    相关资源
    最近更新 更多