Cache match/put 与响应体
Cache API 保存的是 Request 与 Response 对。响应体是一次性流:直接把 response 交给 cache.put 后,调用方不能再读取同一个 body,因此网络响应通常要先 clone()。
可运行实验
把下面代码放在 HTTP 页面中运行(file:// 页面无法使用完整的 Service Worker/Cache 行为):
js
const cache = await caches.open('docs-v1')
const request = new Request('/cache-demo.txt', { cache: 'no-store' })
const response = new Response('fresh at ' + Date.now(), {
headers: { 'Content-Type': 'text/plain' }
})
await cache.put(request, response.clone())
console.log('original:', await response.text())
const cached = await cache.match(request)
console.log('cached:', cached?.status, await cached?.text())应看到 original 与 cached 文本相同。删除 clone() 后,先读 body 再 put 会失败,因为响应流已经被消费;反过来也一样。match 未命中时返回 undefined,业务应进入网络请求或离线占位分支。
缓存键与更新
查询参数、请求方法和部分请求头会影响匹配;不要把带用户身份的个性化响应写入公共缓存。使用版本化名称(如 docs-v2)发布新资源,确认新缓存完整后再删除旧缓存,避免更新中途白屏。
配额、安全与清理
缓存空间由浏览器按设备和站点分配,navigator.storage.estimate() 只能提供估算。捕获 QuotaExceededError 后按优先级删除旧版本、可重建资源和过期条目;退出登录时清理所有包含身份信息的缓存。Cache API 不提供加密,敏感数据不能因为“只在同源”就默认安全。
练习
- 分别测试命中、未命中和不同查询参数,记录
match结果。 - 故意消费 response 后再
put,记录异常并用clone()修复。 - 设计 v1→v2 更新顺序,说明清理失败时如何回退。