了解如何使用 Cache API 让应用数据可供离线使用。
Cache API 是一个用于存储和检索网络请求及其相应响应的系统。这些可能是在运行应用的过程中创建的常规请求和响应,也可能是仅出于存储数据以供日后使用而创建的。
Cache API 旨在让服务工件能够缓存网络请求,以便无论网络速度或可用性如何,都能提供快速响应。不过,该 API 还可用作通用存储机制。
在哪些地区推出了?
Cache API 适用于所有新式浏览器。该 API 通过全局 caches 属性公开,因此您可以通过简单的功能检测来测试该 API 是否存在:
const cacheAvailable = 'caches' in self;
您可以通过窗口、iframe、Worker 或 Service Worker 访问 Cache API。
可以存储的内容
缓存仅存储一对 Request 和 Response 对象,分别表示 HTTP 请求和响应。不过,请求和响应可以包含可通过 HTTP 传输的任何类型的数据。
可以存储多少内容?
总之,很多,至少几百兆字节,并且可能有数百 GB 甚至更多。浏览器实现各不相同,但可用存储空间通常取决于设备上的可用存储空间。
创建和打开缓存
如需打开缓存,请使用 caches.open(name) 方法,并将缓存的名称作为单个参数传递。如果命名缓存不存在,则系统会创建该缓存。此方法会返回一个 Promise,该 Promise 会使用 Cache 对象进行解析。
const cache = await caches.open('my-cache');
// do something with cache...
添加到缓存
您可以通过三种方式将项添加到缓存中:add、addAll 和 put。这三种方法都会返回 Promise。
cache.add
首先,有 cache.add()。它接受一个参数,即 Request 或网址 (string)。它会向网络发出请求,并将响应存储在缓存中。如果提取失败,或者响应的状态代码不在 200 范围内,则不会存储任何内容,并且 Promise 会拒绝。请注意,非 CORS 模式的跨源请求无法存储,因为它们会返回 0 的 status。此类请求只能使用 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,该 Promise 会解析为不同类型的值。
| 方法 | 说明 |
|---|---|
arrayBuffer |
返回一个包含正文的 ArrayBuffer,该正文已序列化为字节。
|
blob |
返回 Blob。如果 Response 是使用 Blob 创建的,则这个新的 Blob 具有相同的类型。否则,将使用 Response 的 Content-Type。
|
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 是字符串,浏览器会通过调用 new Request(request) 将其转换为 Request。如果找到匹配条目,该函数会返回一个解析为 Response 的 Promise;否则,会返回 undefined。
为了确定两个 Requests 是否匹配,浏览器不仅会使用网址。如果两个请求具有不同的查询字符串、Vary 标头或 HTTP 方法(GET、POST、PUT 等),则系统会将其视为不同的请求。