Cache API 是一种提供存储机制的接口,用于缓存 Request/Response 对象,通常用于 Service Worker 的生命周期中。它允许将请求和响应存储在浏览器的缓存中,以便稍后使用。
Cache API 是在 window 对象的作用域下暴露的,因此尽管它被定义在 service worker 的标准中,它也可以在 Service Worker 以外的脚本中使用。
一个域可以拥有多个命名的 Cache 对象,开发者可以根据需要创建和管理多个缓存。
要使用 Cache API,通常需要在脚本中处理缓存的更新逻辑,特别是在 Service Worker 中。缓存数据不会自动更新,除非明确进行缓存更新操作;缓存数据也不会自动过期,除非显式地将其删除。可以使用 CacheStorage.open(cacheName) 方法打开一个指定名称的 Cache 对象,并使用 Cache 对象的方法来处理缓存的操作,例如存储和获取请求与响应。
使用 Cache API,开发者可以轻松地将常用的请求和响应存储在缓存中,以提高网页性能和用户体验。它为开发者提供了更多灵活性和控制权,可以根据需要定制缓存的行为和策略。无论是为离线访问提供支持,还是加速资源加载,Cache API 都是一个强大而实用的工具。
当使用Cache API时,你可以执行以下几个关键操作来管理缓存:
- 打开或创建缓存:
使用
caches.open()方法可以打开或创建一个特定名称的缓存。例如:
const cache = await caches.open('my-cache');
- 添加响应到缓存:
使用
Cache.put()方法可以将响应添加到指定的缓存中。你需要传递一个请求对象和相应对象作为参数。例如:
const request = new Request('/api/data');
const response = new Response('{"message": "Cached response"}');
await cache.put(request, response);
与之相关的还有cache.add和cache.addAll。比如add,在功能上等同于调用 fetch(),然后使用 Cache.put() 将 response 添加到 cache 中。
- 从缓存中获取响应:
使用
Cache.match()方法可以从缓存中获取与请求匹配的响应。如果找到匹配的响应,它将作为返回值返回。例如:
const request = new Request('/api/data');
const response = await cache.match(request);
if (response) {
// 处理响应
} else {
// 从网络请求数据
}
- 删除缓存中的响应:
使用
Cache.delete()方法可以从缓存中删除指定的响应。你需要传递一个请求对象作为参数。例如:
const request = new Request('/api/data');
await cache.delete(request);
- 清除缓存:
使用
caches.delete()方法可以清除整个缓存中的所有响应。例如:
await caches.delete('my-cache');
以下是个测试页面,重点看控制台的打印:
<!DOCTYPE html>
<html>
<head>
<title>缓存示例</title>
<script>
async function main() {
const cache = await caches.open('v1');
const jsFileUrl = './aa.js';
try {
const response = await cache.match(jsFileUrl);
if (response) {
console.info("from cache");
console.log(await response.text());
} else {
const networkResponse = await fetch(jsFileUrl);
const clonedResponse = networkResponse.clone();
await cache.put(jsFileUrl, clonedResponse);
const text = await networkResponse.text();
console.info("from network", text);
}
} catch (error) {
console.error("An error occurred:", error);
}
}
main();
</script>
</head>
<body>
<!-- 页面内容 -->
</body>
</html>
访问这个HTML页面,第一次是没有缓存,但当有了缓存以后,即使你修改了aa.js的内容,也是无济于事。只能修改版本,比如caches.open('v1')改为v2。
内容在F12的缓存空间里可以找到,也能对应的删除:
Deno也实现了Cache API,所以就能用它做些有意思的事情了。比如说,我们以前要完整地缓存一个接口响应,可能需要把响应的Body和Headers都存储在Map对象中,如果要持久化就更麻烦,得序列化为JSON,再存储到本地文件里。而现在只需要以下几行代码:
import { serve } from "https://deno.land/std@0.158.0/http/server.ts";
// Open a cache named v1.
const CACHE = await caches.open("v1");
serve(async (req: Request) => {
// Requests after first request are served from cache.
const res = await CACHE.match(req);
if (res) {
res.headers.set("x-cache-hit", "true");
return res;
}
const { searchParams } = new URL(req.url);
const name = searchParams.get("name");
const response = new Response(`Hello ${name}!`);
// Put response in cache.
await CACHE.put(req, response.clone());
return response;
});
这样,同一个路径的请求都被缓存下来了,即使你重启服务,也仍然生效。
$ deno run -A main.ts
Listening on http://localhost:8000/
Serving from cache http://localhost:8000/
Serving from cache http://localhost:8000/favicon.ico
正常来说,Deno的缓存应该都在DENO_DIR location里,但找了一圈也没有找到在哪儿。所以要清除这个缓存,暂时先在代码中清除吧。