JavaScript 服务工作者(Service Worker)线程中Cache和CacheStorage的主要区别:
| 特性 | Cache | CacheStorage |
|---|---|---|
| 定义 | 表示一个具体的缓存实例,用于存储请求-响应对。 | 是所有缓存(Cache 对象)的容器,提供对多个命名缓存的访问和管理。 |
| 接口类型 | Cache接口 | CacheStorage接口 |
| 获取方式 | 通过caches.open('cache-name')返回一个 Promise,解析为 Cache 实例。 | 通过全局变量caches(即self.caches)直接访问,其类型为 CacheStorage。 |
| -主要方法 | -add(request)- addAll(requests)- put(request, response)- match(request)- delete(request)- keys() | -open(cacheName)→ 返回 Promise<Cache>- has(cacheName)→ 检查是否存在- delete(cacheName)→ 删除整个缓存- keys()→ 获取所有缓存名称 |
| 作用范围 | 单个命名缓存(如'v1-assets')内的操作。 | 管理多个命名缓存的整体集合。 |
| 类比 | 类似于一个“文件夹”中的内容操作。 | 类似于“文件系统根目录”,可创建/删除/列出多个“文件夹”(缓存)。 |
| 使用场景 | 添加、查找或删除特定资源的缓存条目。 | 创建新缓存、清理旧版本缓存、列出当前所有缓存等生命周期管理。 |
💡提示:在 Service Worker 中,
caches是一个全局属性,等价于self.caches,其类型就是CacheStorage。通过它你可以打开具体的Cache实例进行细粒度操作。
例如:
// caches 是 CacheStorage 实例 const cache = await caches.open('my-cache'); // cache 是 Cache 实例 await cache.put('/app.js', new Response('console.log("cached")'));Cache 与 CacheStorage 全部方法对比表
| 类别 | 方法签名 | 返回值类型 | 功能说明 |
|---|---|---|---|
CacheStorage(通过caches访问) | open(cacheName) | Promise<Cache> | 打开指定名称的缓存;若不存在则创建并返回新 Cache 实例。 |
has(cacheName) | Promise<boolean> | 检查是否存在指定名称的缓存。 | |
delete(cacheName) | Promise<boolean> | 删除指定名称的整个缓存;成功删除返回true,否则false。 | |
keys() | Promise<string[]> | 返回当前所有缓存名称的数组。 | |
Cache(通过caches.open()获取) | match(request, options?) | Promise<Response | undefined> | 在缓存中匹配一个请求,返回对应的响应(或 undefined)。 |
matchAll(request?, options?) | Promise<Response[]> | 匹配所有符合条件的响应(可选请求和选项)。 | |
add(request) | Promise<void> | 抓取指定请求并将其响应存入缓存(等价于fetch + put)。 | |
addAll(requests) | Promise<void> | 批量抓取多个请求并缓存其响应(原子操作:任一失败则全部不缓存)。 | |
put(request, response) | Promise<void> | 将指定请求-响应对直接存入缓存(需注意响应可读流只能消费一次)。 | |
delete(request, options?) | Promise<boolean> | 从缓存中删除匹配的请求-响应对;删除成功返回true。 | |
keys(request?, options?) | Promise<Request[]> | 返回缓存中所有(或匹配的)请求对象数组。 |
📌 补充说明
options参数(可选)可包含:ignoreSearch: 忽略 URL 查询字符串(?a=1)。ignoreMethod: 忽略请求方法(默认只匹配 GET)。ignoreVary: 忽略Vary响应头。prefixMatch: (非标准,部分浏览器可能支持)前缀匹配。
注意事项:
Cache.add()和addAll()会发起真实网络请求,因此需确保资源可访问。Cache.put()要求传入的Response对象是未被使用过的(因为 Body 是不可重用的流)。- 所有方法均为异步,返回
Promise。 CacheStorage是缓存的“顶层容器”,而Cache是具体缓存的“操作接口”。
💡 示例速览
// CacheStorage 操作 await caches.has('v1'); // 检查是否存在 const cache = await caches.open('v1'); // 获取 Cache 实例 await caches.delete('old-v1'); // 删除旧缓存 const names = await caches.keys(); // ['v1', 'assets'] // Cache 操作 await cache.add('/index.html'); await cache.put('/api/config', new Response(JSON.stringify({}))); const res = await cache.match('/index.html'); await cache.delete('/temp-file'); const requests = await cache.keys();此表覆盖了截至2025 年Web 标准中Cache和CacheStorage接口的全部官方方法。
CacheStorage() 也有match方法?
Qwen3-Max
没有,CacheStorage接口本身没有match()方法。
✅ 正确理解:
match()是Cache接口的方法,用于在某个具体缓存(Cache 实例)中查找匹配的请求。CacheStorage(即全局的caches)不直接提供match()方法,因为它管理的是多个命名缓存(Cache 对象)的集合,而不是缓存条目本身。
📌 常见误解澄清
你不能这样写:
// ❌ 错误!CacheStorage 没有 match 方法 const response = await caches.match('/some-url');但你可以遍历所有缓存手动实现类似功能,或者更常见的是:先打开特定缓存再 match:
// ✅ 正确方式:先 open 一个 Cache,再 match const cache = await caches.open('my-cache'); const response = await cache.match('/some-url');或者,在 Service Worker 的fetch事件中,通常使用:
self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request) // ← 注意:这是全局快捷方式! ); });⚠️ 这里
caches.match(request)看起来像是 CacheStorage 的方法,但实际上它是CacheStorage接口的一个便捷别名(convenience method)!
🔍 补充说明:caches.match()到底是什么?
根据 MDN 和 W3C 规范,CacheStorage确实定义了一个match()方法!
所以,结论更新如下:
✅
CacheStorage确实有match()方法,但它不是用来查单个缓存,而是在所有已创建的缓存中按顺序查找第一个匹配项。
✅ 官方方法签名(来自规范)
caches.match(request, options?)- 作用:遍历当前 origin 下所有缓存(按创建顺序?实际是实现定义),返回第一个匹配该请求的响应。
- 等价于:
const keys = await caches.keys(); for (const key of keys) { const cache = await caches.open(key); const res = await cache.match(request, options); if (res) return res; } return undefined;
🆕 更新后的完整答案:
| 接口 | 是否有match()方法? | 行为 |
|---|---|---|
Cache | ✅ 有 | 在当前缓存实例中匹配请求。 |
CacheStorage | ✅ 有(常被忽略!) | 在所有命名缓存中查找第一个匹配项。 |
✅ 所以:
CacheStorage确实有match()方法,但它的用途和Cache.match()不同。
💡 使用建议
- 如果你知道资源在哪个缓存(如
'assets-v1'),用cache.match()更高效。 - 如果不确定缓存在哪个名字里(比如清理旧缓存后只剩最新版),可以用
caches.match()全局查找。 - 在 Service Worker 的
fetch事件中,caches.match(event.request)是常见模式,正是调用了CacheStorage.match()。
📚 参考资料
- MDN: CacheStorage.match()
- W3C Service Workers Spec - CacheStorage
✅总结:
是的,CacheStorage有match()方法,用于跨所有缓存查找第一个匹配项。此前认为“没有”是常见误解。