瞭解如何使用 Cache API 將應用程式資料設為可離線存取。
Cache API 是用於儲存及擷取網路的系統 和對應的回應這些可能是一般要求 以及系統在應用程式執行過程中產生的回應 僅供儲存資料供日後使用。
已建立 Cache API,讓服務工作站可以快取網路要求 方便他們快速回應,無論網路速度或網路速度 提高可用性不過,該 API 也可做為一般儲存機制使用。
點此查看服務地區
所有新型瀏覽器皆支援 Cache API。是
透過全域 caches
屬性公開,因此您可以測試,
和一個簡單的特徵偵測來呼叫 API
const cacheAvailable = 'caches' in self;
Cache API 可透過視窗、iframe、工作站或 Service Worker 存取。
可儲存的內容
快取只會儲存 Request
與
Response
物件,代表 HTTP 要求和回應,
。不過,要求和回應可以包含任何類型的資料
支援透過 HTTP 轉移的資料
可以儲存多少?
簡單來說,至少會很多幾百 MB,甚至可能會 數百 GB 以上每種瀏覽器導入方式各有不同,但所需 通常享有儲存空間容量 裝置。
建立及開啟快取
如要開啟快取,請使用 caches.open(name)
方法,並傳遞
做為單一參數如果指定的快取不存在,
已建立。這個方法會傳回一個 Promise
,該 Promise
會以 Cache
物件來解析。
const cache = await caches.open('my-cache');
// do something with cache...
新增至快取
將項目新增至快取的方式有三種:add
、addAll
和 put
。
這三種方法都會傳回 Promise
。
cache.add
第一個是 cache.add()
。這個過程會使用一個參數,例如 Request
或網址 (string
)。它會向網路發出要求並儲存回應
在快取中。如果
擷取失敗,或是回應狀態碼不在 200 範圍內
則系統不會儲存任何內容,且 Promise
會拒絕。請注意,跨來源
無法儲存 CORS 模式的要求,因為要求會傳回 status
的
0
。這類要求只能儲存在 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
物件建構函式接受多種資料,包括
Blob
、ArrayBuffer
、FormData
物件和字串。
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-data 或
application/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 方法 (GET
、POST
、PUT
等)。
您可以忽略部分或全部項目,方法是以 第二個參數
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;
}
這樣一來,您就可以使用 Request
和 Response
物件的任何屬性來
篩選項目。請注意,如果搜尋大型資料集
資料。
建立索引
實作自己搜尋的另一個方法,是維護另外的 索引 項目可供搜尋,並將索引儲存在 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 擔任