CacheStorage - 表示 Cache 对象的存储
CacheStorage
接口表示 Cache
对象的存储。
该接口:
- 提供可以由
ServiceWorker
或其他类型的工作线程或window
范围访问的所有命名缓存的主目录(虽然是 Service Workers 规范对其进行了定义,但是除了服务工作线程之外,您还可以与其他的功能一起使用它。)注意:Chrome 和 Safari 在 HTTPS 中向窗口上下文提供
CacheStorage
接口。除非配置了 SSL 证书,否则window.caches
将是未定义的。 - 维护字符串名称到相应的
Cache
对象的映射。
使用 CacheStorage.open()
获得 Cache
实例。
使用 CacheStorage.match()
来检查给定的 Request
是否是 CacheStorage
对象跟踪的任何 Cache
对象中的键。
您可以通过全局 caches
属性访问 CacheStorage
。
注意:
CacheStorage
总是在不受信任的来源(即那些不使用 HTTPS 的应用程序,尽管将来这种定义可能会变得更加复杂)上以SecurityError
拒绝。在测试时,您可以通过检查 Firefox Devtools 选项 / 齿轮菜单中的 “通过 HTTP 启用 Service Workers(打开工具箱时)” 选项来解决此问题。
注意:
CacheStorage.match()
是一个快捷方法。可以通过以下方式实现与缓存条目匹配的等效功能:从CacheStorage.keys()
返回一组缓存名称,使用CacheStorage.open()
打开每个缓存,然后使用Cache.match()
匹配所需的缓存。
方法
CacheStorage.match()
检查给定的 Request
对象是否是 CacheStorage
对象跟踪的 Cache
对象中的键,返回一个 Promise
,解析为该匹配项。
CacheStorage.has()
返回一个 Promise
,如果存在与 cacheName
相匹配的Cache
对象,则解析为 true
。
CacheStorage.open()
返回一个 Promise
,它解析为与 cacheName
相匹配的 Cache
对象(如果尚不存在,则会创建一个新的缓存。)
CacheStorage.delete()
查找与 cacheName
匹配的 Cache
对象,如果找到,则删除 Cache
对象,并返回一个 Promise
解析为 true
。如果没有找到 Cache
对象,则解析为 false
。
CacheStorage.keys()
返回一个 Promise
,该数组将解析为包含与 CacheStorage
跟踪的所有命名 Cache
对象相对应的字符串的数组。使用此方法可以迭代所有 Cache
对象的列表。
实例
此代码段来自 sw-test 实例(请参阅 sw-test 在线运行。)此服务工作线程脚本等待 InstallEvent
触发,然后运行 waitUntil
来处理应用程序的安装过程。它包括调用 CacheStorage.open
创建新的缓存,然后使用 Cache.addAll
向其中添加一系列资源。
在第二个代码块中,我们等待 FetchEvent
触发。我们构造一个自定义响应,如下所示:
- 检查在
CacheStorage
中是否找到与请求匹配的内容。如果是这样,那就处理它。 - 如果不是,那么从网络获取请求,然后再打开在第一个块中创建的缓存,并使用
Cache.put
(cache.put(event.request, response.clone())
)向其添加请求的副本。 - 如果失败(例如,由于网络中断),则返回一个后备响应。
最后,使用 FetchEvent.respondWith
返回自定义响应。
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('v1').then(function(cache) {
return cache.addAll([
'/sw-test/',
'/sw-test/index.html',
'/sw-test/style.css',
'/sw-test/app.js',
'/sw-test/image-list.js',
'/sw-test/star-wars-logo.jpg',
'/sw-test/gallery/bountyHunters.jpg',
'/sw-test/gallery/myLittleVader.jpg',
'/sw-test/gallery/snowTroopers.jpg'
]);
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(caches.match(event.request).then(function(response) {
// caches.match() 始终会解析,但如果成功,响应才有值
if (response !== undefined) {
return response;
} else {
return fetch(event.request).then(function (response) {
// 响应只能使用一次。我们需要保存克隆以将一个副本放入缓存并提供第二个副本
let responseClone = response.clone();
caches.open('v1').then(function (cache) {
cache.put(event.request, responseClone);
});
return response;
}).catch(function () {
return caches.match('/sw-test/gallery/myLittleVader.jpg');
});
}
}));
});
该代码段展示了如何在服务工作线程上下文之外使用 API,并使用 await
运算符来编写更具可读性的代码。
// 尝试从高速缓存中获取数据,如果没有则回退到获取实时数据。
async function getData() {
const cacheVersion = 1;
const cacheName = `myapp-${ cacheVersion }`;
const url = 'https://jsonplaceholder.typicode.com/todos/1';
let cachedData = await getCachedData( cacheName, url );
if ( cachedData ) {
console.log( '检索缓存的数据' );
return cachedData;
}
console.log( '获取新数据' );
const cacheStorage = await caches.open( cacheName );
await cacheStorage.add( url );
cachedData = await getCachedData( cacheName, url );
await deleteOldCaches( cacheName );
return cachedData;
}
// 从缓存中获取数据。
async function getCachedData( cacheName, url ) {
const cacheStorage = await caches.open( cacheName );
const cachedResponse = await cacheStorage.match( url );
if ( ! cachedResponse || ! cachedResponse.ok ) {
return false;
}
return await cachedResponse.json();
}
// 删除任何旧的缓存,给用户留出磁盘空间。
async function deleteOldCaches( currentCache ) {
const keys = await caches.keys();
for ( const key of keys ) {
const isOurCache = 'myapp-' === key.substr( 0, 6 );
if ( currentCache === key || ! isOurCache ) {
continue;
}
caches.delete( key );
}
}
try {
const data = await getData();
console.log( { data } );
} catch ( error ) {
console.error( { error } );
}
规范
规范 | 状态 | 备注 |
---|---|---|
Service Workers CacheStorage 的定义 |
工作草案 | 初始定义。 |
桌面浏览器兼容性
特性 | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|---|
基础支持 | 4012 | ≤18 | 443 | 不支持 | 27 | 11.1 |
delete | 40 | 16 | 443 | 不支持 | 27 | 11.1 |
has | 40 | 16 | 443 | 不支持 | 27 | 11.1 |
keys | 40 | 16 | 443 | 不支持 | 27 | 11.1 |
match | 54 406 | 16 | 443 | 不支持 | 41 276 | 11.1 |
open | 40 | 16 | 443 | 不支持 | 27 | 11.1 |
Secure context required | 65 | ≤79 | 44 | 不支持 | 52 | 支持 |
移动浏览器兼容性
特性 | Android | Chrome for Android | Edge mobile | Firefox for Android | IE mobile | Opera Android | iOS Safari |
---|---|---|---|---|---|---|---|
基础支持 | 4012 | 4012 | 未知 | 44 | 未知 | 27 | 支持 |
delete | 40 | 40 | 未知 | 44 | 未知 | 27 | 支持 |
has | 40 | 40 | 未知 | 44 | 未知 | 27 | 支持 |
keys | 40 | 40 | 未知 | 44 | 未知 | 27 | 支持 |
match | 54 406 | 54 406 | 未知 | 44 | 未知 | 41 276 | 支持 |
open | 40 | 40 | 未知 | 44 | 未知 | 27 | 支持 |
Secure context required | 65 | 65 | 未知 | 44 | 未知 | 47 | 支持 |
1. 从版本 43 开始,可以从 Window
访问。
2. 从版本 43 开始,可以从 WorkerGlobalScope
访问。
3. 在 Firefox 45 和 52 扩展支持版本(ESR)中,服务工作线程(和 Push)已被禁用。
4. 从 Samsung Internet 4.0 开始,可以从 Window
访问。
5. 从 Samsung Internet 4.0 开始,可以从 WorkerGlobalScope
访问。
6. options 参数仅支持 ignoreSearch
和 cacheName
。