识别Service Worker缓存中的过时缓存条目

时间:2018-06-13 09:50:58

标签: javascript http caching browser-cache 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标头,计算到期时间并与当前时间进行比较。

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

想象一下,客户端时间已经过了一天(有时可能会发生这种情况),现在缓存条目的缓存时间可能比预期的更长或更短。

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

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

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

是否有人知道如何正确识别浏览器等陈旧缓存条目?

1 个答案:

答案 0 :(得分:0)

  

遗憾的是,此解决方案无法工作,因为网络响应不可更改。顺便说一句:复制响应以添加此附加信息不是一个选择。

这实际上是可行的。

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

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
  })
})

另一种更简单但棘手的解决方案是,仅在响应对象上创建一个新属性,而不是依赖于标头对象:

response.__time_fetched = new Date()