Cache
注意:此功能在 Web Workers 中可用。
Cache 接口提供了一种持久化存储机制,用于存储 Request / Response 对象对,这些对象被缓存在长寿命内存中。Cache 对象的生命周期取决于浏览器,但单个源的脚本通常可以依赖于先前填充的 Cache 对象。请注意,Cache 接口既暴露给窗口作用域,也暴露给 worker。您不必将其与 service worker 结合使用,即使它是在 service worker 规范中定义的。
一个源可以有多个命名 Cache 对象。您负责实现脚本(例如,在 ServiceWorker 中)如何处理 Cache 更新。Cache 中的项目不会自动更新,除非明确请求;它们不会过期,除非被删除。使用 CacheStorage.open() 来打开特定的命名 Cache 对象,然后调用任何 Cache 方法来维护 Cache。
您还负责定期清理缓存条目。每个浏览器对给定源可以使用的缓存存储量都有硬性限制。可以通过 StorageManager.estimate() 方法估算 Cache 配额使用情况。浏览器会尽最大努力管理磁盘空间,但它可能会删除源的 Cache 存储。浏览器通常会删除一个源的所有数据,或者不删除任何数据。请确保通过名称对缓存进行版本化,并仅使用可以安全操作它们的脚本版本中的缓存。有关更多信息,请参阅 删除旧缓存。
注意: 键匹配算法取决于值的 VARY 头。因此,匹配新键需要查看 Cache 对象中条目的键和值。
注意: 缓存 API 不遵守 HTTP 缓存头。
实例方法
Cache.match()-
返回一个
Promise,该 Promise 解析为Cache对象中第一个匹配请求的响应。 Cache.matchAll()-
返回一个
Promise,该 Promise 解析为Cache对象中所有匹配响应的数组。 Cache.add()-
接收一个 URL,检索它,并将结果响应对象添加到给定的缓存中。这在功能上等同于调用
fetch(),然后使用put()将结果添加到缓存。 Cache.addAll()-
接收一个 URL 数组,检索它们,并将结果响应对象添加到给定的缓存中。
Cache.put()-
接收请求及其响应,并将它们添加到给定的缓存中。
Cache.delete()-
查找键为请求的
Cache条目,返回一个Promise,如果找到并删除了匹配的Cache条目,则该 Promise 解析为true。如果未找到Cache条目,则 Promise 解析为false。 Cache.keys()-
返回一个
Promise,该 Promise 解析为Cache键的数组。
示例
此代码片段来自 service worker 选择性缓存示例。(请参阅 选择性缓存实时演示) 代码使用 CacheStorage.open() 来打开任何 Content-Type 头以 font/ 开头的 Cache 对象。
然后,代码使用 Cache.match() 来检查缓存中是否已有匹配的字体,如果有,则返回它。如果不存在匹配的字体,代码将从网络获取字体,并使用 Cache.put() 将获取的资源缓存起来。
代码处理从 fetch() 操作抛出的异常。请注意,HTTP 错误响应(例如 404)不会引发异常。它将返回一个具有相应错误代码的正常响应对象。
代码片段还展示了 service worker 使用的缓存版本化的最佳实践。虽然在此示例中只有一个缓存,但相同的方法可用于多个缓存。它将缓存的简短标识符映射到特定的、版本化的缓存名称。代码还会删除所有未在 CURRENT_CACHES 中命名的缓存。
在代码示例中,caches 是 ServiceWorkerGlobalScope 的一个属性。它包含 CacheStorage 对象,通过它可以访问 CacheStorage 接口。
注意: 在 Chrome 中,访问 chrome://inspect/#service-workers 并点击已注册的 service worker 下方的“inspect”链接,可以查看 service-worker.js 脚本执行的各种操作的日志记录语句。
const CACHE_VERSION = 1;
const CURRENT_CACHES = {
font: `font-cache-v${CACHE_VERSION}`,
};
self.addEventListener("activate", (event) => {
// Delete all caches that aren't named in CURRENT_CACHES.
// While there is only one cache in this example, the same logic
// will handle the case where there are multiple versioned caches.
const expectedCacheNamesSet = new Set(Object.values(CURRENT_CACHES));
event.waitUntil(
caches.keys().then((cacheNames) =>
Promise.all(
cacheNames.map((cacheName) => {
if (!expectedCacheNamesSet.has(cacheName)) {
// If this cache name isn't present in the set of
// "expected" cache names, then delete it.
console.log("Deleting out of date cache:", cacheName);
return caches.delete(cacheName);
}
return undefined;
}),
),
),
);
});
self.addEventListener("fetch", (event) => {
console.log("Handling fetch event for", event.request.url);
event.respondWith(
caches
.open(CURRENT_CACHES.font)
.then((cache) => cache.match(event.request))
.then((response) => {
if (response) {
// If there is an entry in the cache for event.request,
// then response will be defined and we can just return it.
// Note that in this example, only font resources are cached.
console.log(" Found response in cache:", response);
return response;
}
// Otherwise, if there is no entry in the cache for event.request,
// response will be undefined, and we need to fetch() the resource.
console.log(
" No response for %s found in cache. About to fetch " +
"from network…",
event.request.url,
);
// We call .clone() on the request since we might use it
// in a call to cache.put() later on.
// Both fetch() and cache.put() "consume" the request,
// so we need to make a copy.
// (see https://mdn.org.cn/en-US/docs/Web/API/Request/clone)
return fetch(event.request.clone()).then((response) => {
console.log(
" Response for %s from network is: %O",
event.request.url,
response,
);
if (
response.status < 400 &&
response.headers.has("content-type") &&
response.headers.get("content-type").match(/^font\//i)
) {
// This avoids caching responses that we know are errors
// (i.e. HTTP status code of 4xx or 5xx).
// We also only want to cache responses that correspond
// to fonts, i.e. have a Content-Type response header that
// starts with "font/".
// Note that for opaque filtered responses
// https://fetch.spec.whatwg.org/#concept-filtered-response-opaque
// we can't access to the response headers, so this check will
// always fail and the font won't be cached.
// All of the Google Web Fonts are served from a domain that
// supports CORS, so that isn't an issue here.
// It is something to keep in mind if you're attempting
// to cache other resources from a cross-origin
// domain that doesn't support CORS, though!
console.log(" Caching the response to", event.request.url);
// We call .clone() on the response to save a copy of it
// to the cache. By doing so, we get to keep the original
// response object which we will return back to the controlled
// page.
// https://mdn.org.cn/en-US/docs/Web/API/Request/clone
cache.put(event.request, response.clone());
} else {
console.log(" Not caching the response to", event.request.url);
}
// Return the original response object, which will be used to
// fulfill the resource request.
return response;
});
})
.catch((error) => {
// This catch() will handle exceptions that arise from the match()
// or fetch() operations.
// Note that a HTTP error response (e.g. 404) will NOT trigger
// an exception.
// It will return a normal response object that has the appropriate
// error code set.
console.error(" Error in fetch handler:", error);
throw error;
}),
);
});
Cookie 和 Cache 对象
Fetch API 要求在从 fetch() 返回 Response 对象之前,删除 Set-Cookie 头。因此,存储在 Cache 中的 Response 将不包含 Set-Cookie 头,因此不会导致任何 Cookie 被存储。
规范
| 规范 |
|---|
| Service Workers # cache-interface |
浏览器兼容性
加载中…