CacheStorage

安全上下文:此功能仅在安全上下文(HTTPS)中可用,在某些或所有支持的浏览器中。

注意:此功能在Web Workers中可用。

CacheStorage 接口表示 Cache 对象的存储。

该接口

  • 提供所有可由 ServiceWorker 或其他类型的 worker 或 window 范围访问的命名缓存的主目录(您不限于仅在 service worker 中使用它)。
  • 维护字符串名称到相应 Cache 对象的映射。

使用 CacheStorage.open() 获取 Cache 实例。

使用 CacheStorage.match() 检查给定的 Request 是否是 CacheStorage 对象跟踪的任何 Cache 对象中的键。

您可以通过窗口中的 Window.caches 属性或 worker 中的 WorkerGlobalScope.caches 属性访问 CacheStorage

注意:CacheStorage 始终在不受信任的来源(即未使用 HTTPS 的来源,尽管此定义将来可能会变得更复杂)上拒绝并显示 SecurityError。在 Firefox 上进行测试时,您可以通过检查 Firefox Devtools 选项/齿轮菜单中的在 HTTP 上启用 Service Workers(当工具箱打开时)选项来解决此问题。此外,由于 CacheStorage 需要文件系统访问权限,因此它可能在 Firefox 的隐私模式下不可用。

注意:CacheStorage.match() 是一种便捷方法。可以通过从 CacheStorage.keys() 返回缓存名称数组,使用 CacheStorage.open() 打开每个缓存,并使用 Cache.match() 匹配所需的缓存来实现与缓存条目匹配的等效功能。

实例方法

CacheStorage.match()

检查给定的 Request 是否是 CacheStorage 对象跟踪的任何 Cache 对象中的键,并返回一个解析为该匹配项的 Promise

CacheStorage.has()

返回一个解析为 truePromise,如果存在与 cacheName 匹配的 Cache 对象。

CacheStorage.open()

返回一个解析为与 cacheName 匹配的 Cache 对象的 Promise(如果该缓存尚不存在,则会创建一个新缓存)。

CacheStorage.delete()

查找与 cacheName 匹配的 Cache 对象,如果找到,则删除 Cache 对象并返回一个解析为 truePromise。如果未找到 Cache 对象,则解析为 false

CacheStorage.keys()

返回一个将解析为包含与 CacheStorage 跟踪的所有命名 Cache 对象对应的字符串的数组的 Promise。使用此方法迭代所有 Cache 对象的列表。

示例

此代码片段来自 MDN 的简单 service worker 示例(请参阅正在运行的简单 service worker)。此 service worker 脚本等待 install 事件触发,然后运行 waitUntil 来处理应用程序的安装过程。这包括调用 CacheStorage.open 创建一个新的缓存,然后使用 Cache.addAll 向其中添加一系列资源。

在第二个代码块中,我们等待 FetchEvent 触发。我们像这样构造一个自定义响应

  1. 检查在 CacheStorage 中是否找到请求的匹配项。如果是,则提供该匹配项。
  2. 如果不是,则从网络获取请求,然后打开在第一个块中创建的缓存,并使用 Cache.putcache.put(event.request, response.clone()))向其中添加请求的克隆。
  3. 如果失败(例如,由于网络中断),则返回备用响应。

最后,使用 FetchEvent.respondWith 返回自定义响应最终等于的值。

js
self.addEventListener("install", (event) => {
  event.waitUntil(
    caches
      .open("v1")
      .then((cache) =>
        cache.addAll([
          "/",
          "/index.html",
          "/style.css",
          "/app.js",
          "/image-list.js",
          "/star-wars-logo.jpg",
          "/gallery/bountyHunters.jpg",
          "/gallery/myLittleVader.jpg",
          "/gallery/snowTroopers.jpg",
        ]),
      ),
  );
});

self.addEventListener("fetch", (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      // caches.match() always resolves
      // but in case of success response will have value
      if (response !== undefined) {
        return response;
      } else {
        return fetch(event.request)
          .then((response) => {
            // response may be used only once
            // we need to save clone to put one copy in cache
            // and serve second one
            let responseClone = response.clone();

            caches.open("v1").then((cache) => {
              cache.put(event.request, responseClone);
            });
            return response;
          })
          .catch(() => caches.match("/gallery/myLittleVader.jpg"));
      }
    }),
  );
});

此代码段演示了如何在 service worker 上下文之外使用 API,并使用 await 运算符使代码更易读。

js
// Try to get data from the cache, but fall back to fetching it live.
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("Retrieved cached data");
    return cachedData;
  }

  console.log("Fetching fresh data");

  const cacheStorage = await caches.open(cacheName);
  await cacheStorage.add(url);
  cachedData = await getCachedData(cacheName, url);
  await deleteOldCaches(cacheName);

  return cachedData;
}

// Get data from the cache.
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();
}

// Delete any old caches to respect user's disk space.
async function deleteOldCaches(currentCache) {
  const keys = await caches.keys();

  for (const key of keys) {
    const isOurCache = key.startsWith("myapp-");
    if (currentCache === key || !isOurCache) {
      continue;
    }
    caches.delete(key);
  }
}

try {
  const data = await getData();
  console.log({ data });
} catch (error) {
  console.error({ error });
}

规范

规范
Service Workers
# cachestorage-interface

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅