CacheStorage
============

**`CacheStorage`** インターフェイスは、`Cache` オブジェクトのストレージを表します。

このインターフェイスは、

* `ServiceWorker` や他の種類のワーカーまたは `window` のスコープからアクセスできる、すべての名前付きキャッシュのマスターディレクトリーを提供します（サービスワーカーでの使用には限定されません）。
* 対応する `Cache` オブジェクトへの文字列名のマッピングを維持します。

`CacheStorage.open()` を使用して、`Cache` インスタンスを取得します。

`CacheStorage.match()` を使用して、所与の `Request` が `CacheStorage` オブジェクトが追跡する `Cache` オブジェクトのキーであるかどうかを確認します。

グローバルな `caches` プロパティを介して `CacheStorage` にアクセスできます。

**メモ:** `CacheStorage` は、信頼されていないオリジン（つまり、 HTTPS を使用しないオリジンですが、この定義は将来より複雑になる可能性があります）では常に拒否し、 `SecurityError` となります。 Firefox でテストする場合は、 Firefox 開発者ツールのオプション/ギアメニューの **HTTP による Service Worker を有効化 (ツールボックスを開いたとき)** オプションをチェックすることで回避することが可能です。さらに、 `CacheStorage` はファイルシステムへのアクセスを必要とするため、Firefoxのプライベートモードでは利用できない場合があります。

**メモ:** `CacheStorage.match()` は便利なメソッドです。 キャッシュエントリと一致する同等の機能を実装するには、`CacheStorage.keys()` からキャッシュ名の配列を返し、`CacheStorage.open()` で各キャッシュを開き、`Cache.match()` で必要なものと一致させます。

**注:** この機能は Web Worker 内で利用可能です

**安全なコンテキスト用:** この機能は一部またはすべての対応しているブラウザーにおいて、安全なコンテキスト (HTTPS) でのみ利用できます。

インスタンスメソッド
----------

`CacheStorage.match()`

所与の `Request` が、`CacheStorage` オブジェクトが追跡する `Cache` オブジェクトのキーであるかどうかを確認し、その一致で解決する `Promise` を返します。

`CacheStorage.has()`

`Promise` を返します。これは、 `cacheName` に一致する `Cache` オブジェクトが存在する場合、`true` に解決されます。

`CacheStorage.open()`

`Promise` を返します。これは、 `cacheName` に一致する `Cache` オブジェクトに解決されます（まだ存在しない場合は新しいキャッシュが作成されます）。

`CacheStorage.delete()`

`cacheName` に一致する `Cache` オブジェクトを見つけ、見つかった場合は `Cache` オブジェクトを削除し、 `true` に解決される `Promise` を返します。 `Cache` オブジェクトが見つからない場合、`false` に解決されます。

`CacheStorage.keys()`

`Promise` を返します。これは、 `CacheStorage` によって追跡されるすべての名前付き `Cache` オブジェクトに対応する文字列を含む配列で解決されます。このメソッドを使用して、すべての `Cache` オブジェクトのリストを反復処理します。

例
-

このコードスニペットは、MDN の単純なサービスワーカーの例からのものです（単純なサービスワーカーがライブで実行するのを見る）。 このサービスワーカーのスクリプトは、 `InstallEvent` が発生するのを待ち、`waitUntil` を実行してアプリのインストールプロセスを処理します。 これは、`CacheStorage.open` を呼び出して新しいキャッシュを作成し、`Cache.addAll` を使用して一連のアセットを追加することで構成されます。

2 番目のコードブロックでは、 `FetchEvent` が発生するのを待ちます。 次のようなカスタムレスポンスを作成します。

1. `CacheStorage` でリクエストに一致するものが見つかったかどうかを確認します。 もしそうなら、それを提供します。
2. そうでない場合は、ネットワークからリクエストを取得し、最初のブロックで作成されたキャッシュも開き、`Cache.put` (`cache.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() は常に解決します
      // ただし、成功の場合はレスポンスに値があります
      if (response !== undefined) {
        return response;
      } else {
        return fetch(event.request)
          .then((response) => {
            // レスポンスは1回のみ使用できます
            // クローンを保存して、1番目のコピーをキャッシュに入れ、
            // 2番目のコピーを提供する必要があります
            let responseClone = response.clone();

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


このスニペットは、サービスワーカーのコンテキストの外部で API を使用する方法を示しており、`await` 演算子を使用してより読みやすいコードにしています。


```js
// キャッシュからデータを取得しようとしますが、フォールバックしてライブで取得します。
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("取得したキャッシュデータ");
    return cachedData;
  }

  console.log("最新データの取得");

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

  return cachedData;
}

// キャッシュからデータを取得します。
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();
}

// 古いキャッシュを削除して、ユーザーのディスク容量を尊重します。
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 });
}
```

仕様書
---

| Specification |
| --- |
| Service Workers # cachestorage-interface |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* サービスワーカーの使用
* `Cache`
* `caches`
* プライベートブラウジング / シークレットモード