了解如何使用 Cache API 让您的应用数据可供离线使用。
Cache API 是一个用于存储和检索网络的系统 请求及其相应的响应。这些可能是常规请求 在运行应用的过程中创建的响应,或者 仅用于存储供日后使用的数据。
Cache API 旨在让 Service Worker 可以缓存网络请求 这样无论网速如何 。不过,API 也可用作常规存储机制。
在哪些地区推出了?
所有新型浏览器都支持 Cache API。时间是
通过全局 caches
属性公开,以便您测试是否存在
对 API 进行简单的特征检测:
const cacheAvailable = 'caches' in self;
浏览器支持
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
可以通过窗口、iframe、Worker 或 Service Worker 访问 Cache API。
可存储的内容
缓存仅存储 Request
和
Response
对象,表示 HTTP 请求和响应;
。但是,请求和响应可以包含任何类型的数据
可通过 HTTP 传输的
可存储多少内容?
简而言之,很多,至少有几百 MB, 数百 GB 或更多。各个浏览器的实施方法会有所不同 可用存储空间通常取决于 。
创建和打开缓存
如需打开缓存,请使用 caches.open(name)
方法,并传递
缓存为单个参数。如果指定的缓存不存在,
创建。此方法会返回使用 Cache
对象进行解析的 Promise
。
const cache = await caches.open('my-cache');
// do something with cache...
添加到缓存
将内容添加到缓存有三种方法 - add
、addAll
和 put
。
所有这三个方法都会返回一个 Promise
。
cache.add
首先是 cache.add()
。它接受一个形参,可以是 Request
,
或网址 (string
)。它会向网络发出请求并存储响应
缓存中。如果
或者响应的状态代码不在 200 范围内,
则系统不会存储任何内容,并且 Promise
会拒绝。请注意,跨源
无法存储未处于 CORS 模式的请求,因为它们返回的 status
0
。此类请求只能使用 put
进行存储。
// Retreive data.json from the server and store the response.
cache.add(new Request('/data.json'));
// Retreive data.json from the server and store the response.
cache.add('/data.json');
cache.addAll
接下来是“cache.addAll()
”。它的工作原理与 add()
类似,
由 Request
对象或网址 (string
) 组成的数组。其工作原理类似于
分别为每个请求调用 cache.add
,但 Promise
如果有任何单个请求未缓存,则会拒绝。
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
在每种情况下,新条目都会覆盖任何匹配的现有条目。 它使用的匹配规则与 检索。
cache.put
最后是 cache.put()
,它允许您存储响应
或者创建并存储您自己的 Response
。需要
参数。第一个可以是 Request
对象,也可以是网址 (string
)。
第二个必须是 Response
,要么来自广告联盟,要么是由您的
代码。
// Retrieve data.json from the server and store the response.
cache.put('/data.json');
// Create a new entry for test.json and store the newly created response.
cache.put('/test.json', new Response('{"foo": "bar"}'));
// Retrieve data.json from the 3rd party site and store the response.
cache.put('https://example.com/data.json');
put()
方法比 add()
或 addAll()
更宽松,
将允许您存储非 CORS 响应或其他
响应代码不在 200 范围内。它将覆盖之前
针对同一请求的响应。
创建 Request 对象
使用所存储内容的网址创建 Request
对象:
const request = new Request('/my-data-store/item-id');
使用 Response 对象
Response
对象构造函数接受多种类型的数据,包括
Blob
、ArrayBuffer
、FormData
对象和字符串。
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
您可以通过设置适当的标头来设置 Response
的 MIME 类型。
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
如果您已检索到 Response
并希望访问其正文,则
几种辅助方法每个参数都会返回一个 Promise
,用于解析
具有不同类型的值
方法 | 说明 |
---|---|
arrayBuffer |
返回包含正文的 ArrayBuffer ,并已序列化为
字节。
|
blob |
返回 Blob 。如果 Response 已创建
具有 Blob 的项,那么这个新的 Blob 将具有相同的
类型。否则,Content-Type
Response 。
|
text |
将正文的字节解释为 UTF-8 编码字符串。 |
json |
将正文的字节解释为 UTF-8 编码的字符串,然后尝试
并将其解析为 JSON 格式。返回生成的对象,或抛出
如果字符串无法解析为 JSON,则返回 TypeError 。
|
formData |
将正文的字节解释为 HTML 形式,编码为
multipart/form-data 或
application/x-www-form-urlencoded 。返回一个
FormData
对象,或者如果无法解析数据,则抛出 TypeError 。
|
body |
返回 ReadableStream 作为正文数据的对象 |
例如:
const response = new Response('Hello world');
const buffer = await response.arrayBuffer();
console.log(new Uint8Array(buffer));
// Uint8Array(11) [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
从缓存中检索
如需在缓存中查找项,您可以使用 match
方法。
const response = await cache.match(request);
console.log(request, response);
如果 request
是一个字符串,浏览器会通过调用以下函数将其转换为 Request
:
new Request(request)
。该函数会返回解析为 Promise
如果找到匹配条目,则返回 Response
,否则返回 undefined
。
为确定两个 Requests
是否匹配,浏览器不会仅使用网址。二
如果这些请求包含不同的查询字符串,
Vary
标头或 HTTP 方法(GET
、POST
、PUT
等)。
您可以通过将 options 对象作为 第二个参数。
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
如果有多个缓存请求匹配,则先创建的那个请求为
返回。如果要检索所有匹配的响应,可以使用
cache.matchAll()
。
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const responses = await cache.matchAll(request, options);
console.log(`There are ${responses.length} matching responses.`);
使用 caches.match()
可一次搜索所有缓存,一种快捷的方法
而不是为每个缓存调用 cache.match()
。
正在搜索
Cache API 不支持搜索请求或响应
但针对 Response
对象的匹配条目除外。不过,您可以
使用过滤功能或创建索引来实现自己的搜索。
过滤
实现自己的搜索的一种方法是遍历所有条目并
以便仅显示您需要的图片假设您要查找
网址以 .png
结尾的项。
async function findImages() {
// Get a list of all of the caches for this origin
const cacheNames = await caches.keys();
const result = [];
for (const name of cacheNames) {
// Open the cache
const cache = await caches.open(name);
// Get a list of entries. Each item is a Request object
for (const request of await cache.keys()) {
// If the request URL matches, add the response to the result
if (request.url.endsWith('.png')) {
result.push(await cache.match(request));
}
}
}
return result;
}
这样,您就可以使用 Request
和 Response
对象的任何属性来
对条目进行过滤。请注意,如果您搜索大量数据集,则速度会很慢
数据。
创建索引
实施您自己的搜索的另一种方法是维护单独的 可以搜索并将索引存储在 IndexedDB 中的条目。由于这是 IndexedDB 专为其设计 大量条目。
如果您将 Request
的网址与可搜索的属性一起存储
则可在执行搜索后轻松检索到正确的缓存条目。
删除内容
如需从缓存中删除项,请执行以下操作:
cache.delete(request);
其中 request 可以是 Request
或网址字符串。此方法还接受
与 cache.match
相同的选项对象,它允许您删除多个
Request
/Response
对。
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
删除缓存
如需删除缓存,请调用 caches.delete(name)
。此函数返回一个
Promise
,如果缓存存在但已被删除,则解析为 true
;或者
否则为 false
。
谢谢
感谢本文原版作者 Mat Scales, 首次出现在 WebFundamentals 上