javascript - 识别 Service Worker 缓存中的陈旧缓存条目

标签 javascript http caching browser-cache service-worker

我希望我的 Service Worker 在某些情况下表现得像浏览器缓存一样。这意味着当响应缓存命中时,我首先需要确保资源没有过期。例如,我可以这样做:

const cacheControl = response.headers.get('cache-control');
const date = new Date(response.headers.get('date'));
const age = parseInt(response.headers.get('age') || '0', 10);

const maxAge = getMaxAge(cacheControl);
const expiration = date.getTime() + 1000 * (maxAge - age);

const isFresh = Date.now() < expiration;

我从缓存的响应中获取 cache-controldateage header ,计算过期时间并与当前时间进行比较。

这种方法的唯一问题是它可能会受到客户端和服务器之间时钟漂移的影响。这是因为日期头是在服务器端生成的,但最终与本地客户端时间进行比较。

想象一下,客户端时间延迟了一天(不幸的是有时会发生),现在缓存条目的缓存时间可能比预期长或短一天。

我想要的解决方案是在缓存中存储响应时将获取时间添加为自定义 header 。然后我可以使用这个自定义 header 而不是

const networkResponse = fetch(request);
// does not work, headers are immutable
networkResponse.headers.append('x-time-fetched', Date.now());
cach.put(request, networkResponse);

遗憾的是,这个解决方案不起作用,因为网络响应是不可变的。顺便说一句:复制响应以添加此附加信息不是一种选择。

有人知道如何像浏览器一样正确识别过时的缓存条目吗?

最佳答案

Sadly, this solution does not work because the network response is not mutable. Btw: copying the response to add this additional information is not an option.

这实际上是非常可行的。

一个解决方案是创建一个新的 Response object并手动添加新 header 。

const newHeaders = new Headers()
for (let entry of response.headers.entries()) {
  headers.append(entry[0], entry[1])
}
headers.append('x-time-fetched', Date.now())

const newResponse = await response.blob().then(blob => {
  return new Response(blob, {
    status: response.status,
    statusText: res.statusText,
    headers: headers
  })
})

另一个更简单但有难度的解决方案是在响应对象上创建一个新属性,而不是依赖于 header 对象:

response.__time_fetched = new Date()

关于javascript - 识别 Service Worker 缓存中的陈旧缓存条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50834217/

相关文章:

c# - 本地缓存库 C#(持久且加密)

javascript - Protractor Typescript 在 tsConfig 文件中将 ts 转换为 js 文件时出现问题。我该如何解决?

java - 服务器自动发现节点的算法?

c# - WCF 缓存服务器端

visual-studio - Umbraco Backoffice 没有注册对自定义属性编辑器所做的更改

http - Firefox 加载页面两次(或 3 次),在 firebug 中显示为 Abort 200

javascript - event.preventDefault() 适用于 Chrome、Firefox,但不适用于 Safari

javascript - 单击 href 选择隐藏的单选按钮

javascript - 如何挂接套件 :start/end with Buster. js?

spring - @ExceptionHandler + @ResponseStatus