Cache API:快速指南

瞭解如何使用 Cache API 將應用程式資料設為可離線存取。

Cache API 是用於儲存及擷取網路的系統 和對應的回應這些可能是一般要求 以及系統在應用程式執行過程中產生的回應 僅供儲存資料供日後使用。

已建立 Cache API,讓服務工作站可以快取網路要求 方便他們快速回應,無論網路速度或網路速度 提高可用性不過,該 API 也可做為一般儲存機制使用。

點此查看服務地區

所有新型瀏覽器皆支援 Cache API。是 透過全域 caches 屬性公開,因此您可以測試, 和一個簡單的特徵偵測來呼叫 API

const cacheAvailable = 'caches' in self;

瀏覽器支援

  • Chrome:40.
  • Edge:16.
  • Firefox:41。
  • Safari:11.1.

資料來源

Cache API 可透過視窗、iframe、工作站或 Service Worker 存取。

可儲存的內容

快取只會儲存 RequestResponse 物件,代表 HTTP 要求和回應, 。不過,要求和回應可以包含任何類型的資料 支援透過 HTTP 轉移的資料

可以儲存多少?

簡單來說,至少會很多幾百 MB,甚至可能會 數百 GB 以上每種瀏覽器導入方式各有不同,但所需 通常享有儲存空間容量 裝置。

建立及開啟快取

如要開啟快取,請使用 caches.open(name) 方法,並傳遞 做為單一參數如果指定的快取不存在, 已建立。這個方法會傳回一個 Promise,該 Promise 會以 Cache 物件來解析。

const cache = await caches.open('my-cache');
// do something with cache...

新增至快取

將項目新增至快取的方式有三種:addaddAllput。 這三種方法都會傳回 Promise

cache.add

第一個是 cache.add()。這個過程會使用一個參數,例如 Request 或網址 (string)。它會向網路發出要求並儲存回應 在快取中。如果 擷取失敗,或是回應狀態碼不在 200 範圍內 則系統不會儲存任何內容,且 Promise 會拒絕。請注意,跨來源 無法儲存 CORS 模式的要求,因為要求會傳回 status0。這類要求只能儲存在 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 物件:

const request = new Request('/my-data-store/item-id');

使用 Response 物件

Response 物件建構函式接受多種資料,包括 BlobArrayBufferFormData 物件和字串。

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, 不同類型的值

方法 說明
arrayBuffer 傳回包含主體 (已序列化為) 的 ArrayBuffer 一個位元組
blob 傳回 Blob。如果 Response 已建立 具有 Blob,則新的 Blob 具有相同 類型。否則,Content-Type 已使用 Response
text 將內文的位元組視為 UTF-8 編碼字串。
json 將內文的位元組解讀為 UTF-8 編碼字串,然後嘗試 就能將其剖析為 JSON傳回產生的物件,或擲回 如果字串無法剖析為 JSON,則為 TypeError
formData 將內文的位元組解譯為 HTML 格式,或編碼為 multipart/form-dataapplication/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 是字串,瀏覽器會呼叫以將其轉換為 Request new Request(request)。這個函式會傳回 Promise,可解析為 如果找到相符的項目,則會傳回 Response,否則會傳回 undefined

為了判斷兩個 Requests 是否相符,瀏覽器不僅使用網址。兩條 如果要求含有不同的查詢字串,就會視為不同 Vary 標頭或 HTTP 方法 (GETPOSTPUT 等)。

您可以忽略部分或全部項目,方法是以 第二個參數

const options = {
  ignoreSearch: true,
  ignoreMethod: true,
  ignoreVary: true
};

const response = await cache.match(request, options);
// do something with the response

如果有多個快取要求符合,系統會優先建立 。如要擷取「所有」相符的回應, cache.matchAll()

const options = {
  ignoreSearch: true,
  ignoreMethod: true,
  ignoreVary: true
};

const responses = await cache.matchAll(request, options);
console.log(`There are ${responses.length} matching responses.`);

使用 caches.match() 即可一次搜尋所有快取 而不是針對每個快取呼叫 cache.match()

搜尋中

Cache API 無法搜尋要求或回應 但針對 Response 物件進行比對。不過, 使用篩選條件或建立索引來實作您自己的搜尋。

篩選

實作自我搜尋的其中一種方法是反覆處理所有項目, 篩選範圍至您想要的項目假設您要 網址結尾為 .png 的項目。

async function findImages() {
  // Get a list of all of the caches for this origin
  const cacheNames = await caches.keys();
  const result = [];

  for (const name of cacheNames) {
    // Open the cache
    const cache = await caches.open(name);

    // Get a list of entries. Each item is a Request object
    for (const request of await cache.keys()) {
      // If the request URL matches, add the response to the result
      if (request.url.endsWith('.png')) {
        result.push(await cache.match(request));
      }
    }
  }

  return result;
}

這樣一來,您就可以使用 RequestResponse 物件的任何屬性來 篩選項目。請注意,如果搜尋大型資料集 資料。

建立索引

實作自己搜尋的另一個方法,是維護另外的 索引 項目可供搜尋,並將索引儲存在 IndexedDB 中。由於這是解碼器的 因此,我們為 IndexedDB 設計而成 大量資料。

如果您將 Request 的網址連同可供搜尋的屬性一併儲存 那麼在執行搜尋後,就能輕鬆擷取正確的快取項目。

刪除項目

如何刪除快取中的項目:

cache.delete(request);

其中的要求可以是 Request 或網址字串。這個方法也使用 與 cache.match 相同的選項物件,可讓您刪除多個 Request/Response 組合。

cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});

刪除快取

如要刪除快取,請呼叫 caches.delete(name)。這個函式會傳回 如果在快取存在且已刪除時,Promise 會解析為 true;或 否則為 false

謝謝

感謝 Mat Scales 撰寫本文的原稿, 才剛在 WebFundamentals 擔任