Dowiedz się, jak używać interfejsu Cache API do udostępniania danych aplikacji offline.
Interfejs Cache API to system do przechowywania i pobierania żądań sieciowych oraz powiązanych z nimi odpowiedzi. Mogą to być zwykłe żądania i odpowiedzi tworzone w trakcie uruchamiania aplikacji lub mogą być tworzone wyłącznie do przechowywania danych do późniejszego wykorzystania.
Interfejs Cache API został utworzony, aby umożliwić mechanizmom Service Worker buforowanie żądań sieciowych, co pozwala na szybkie udzielanie odpowiedzi niezależnie od szybkości sieci i dostępności. Interfejs API może być jednak również używany jako ogólny mechanizm przechowywania danych.
Gdzie jest dostępna?
Interfejs Cache API jest dostępny we wszystkich nowoczesnych przeglądarkach. Jest on ujawniany za pomocą globalnej właściwości caches
, więc możesz przetestować obecność interfejsu API za pomocą prostego wykrywania funkcji:
const cacheAvailable = 'caches' in self;
Interfejs Cache API jest dostępny z poziomu okna, elementu iframe, instancji roboczej lub skryptu service worker.
Co można przechowywać
W pamięci podręcznej przechowywane są tylko pary obiektów Request
i Response
, które odpowiednio reprezentują żądania i odpowiedzi HTTP. Żądania i odpowiedzi mogą jednak zawierać dowolne dane, które można przenosić przez HTTP.
Ile można przechowywać?
W skrócie dużo, co najmniej kilkaset megabajtów, a potencjalnie setki gigabajtów lub więcej. Implementacje przeglądarek są różne, ale ilość dostępnego miejsca zwykle zależy od ilości miejsca dostępnego na urządzeniu.
Tworzenie i otwieranie pamięci podręcznej
Aby otworzyć pamięć podręczną, użyj metody caches.open(name)
, przekazując nazwę pamięci podręcznej jako pojedynczy parametr. Jeśli nazwana pamięć podręczna nie istnieje, zostanie utworzona. Ta metoda zwraca błąd Promise
, który analizuje obiekt Cache
.
const cache = await caches.open('my-cache');
// do something with cache...
Dodawanie do pamięci podręcznej
Istnieją 3 sposoby dodawania elementu do pamięci podręcznej: add
, addAll
i put
.
Wszystkie 3 metody zwracają Promise
.
cache.add
Pierwszy jest cache.add()
. Przyjmuje jeden parametr: Request
lub adres URL (string
). Wysyła żądanie do sieci i zapisuje odpowiedź w pamięci podręcznej. Jeśli pobieranie nie powiedzie się lub jeśli kod stanu odpowiedzi nie mieści się w zakresie 200, nic nie jest zapisywane, a Promise
odrzuca. Pamiętaj, że żądań z innych domen, które nie są w trybie CORS, nie można przechowywać, ponieważ zwracają one status
o wartości 0
. Takie żądania można przechowywać tylko w usłudze 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
Następnie jest cache.addAll()
. Działa podobnie do add()
, ale wykorzystuje tablicę Request
obiektów lub adresów URL (string
). Działa to podobnie jak wywoływanie cache.add
w przypadku każdego pojedynczego żądania, z tą różnicą, że Promise
odrzuca, jeśli pojedyncze żądanie nie jest przechowywane w pamięci podręcznej.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
W każdym z tych przypadków nowy wpis zastąpi dowolny pasujący istniejący wpis. Są one zgodne z tymi samymi regułami dopasowania, które są opisane w sekcji o retrieving.
cache.put
Ostatnim elementem jest cache.put()
, która pozwala zapisać odpowiedź z sieci lub utworzyć i zapisać własną Response
. Potrzeba 2 parametrów. Pierwszą z nich może być obiekt Request
lub adres URL (string
). Drugi musi być obiektem Response
pochodzącym z sieci lub wygenerowanym przez Twój kod.
// 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');
Metoda put()
jest bardziej restrykcyjna niż add()
i addAll()
i umożliwia przechowywanie odpowiedzi innych niż CORS lub innych odpowiedzi, których kod stanu nie mieści się w zakresie 200. Spowoduje to zastąpienie wszystkich
wcześniejszych odpowiedzi na to samo żądanie.
Tworzenie obiektów żądań
Utwórz obiekt Request
, korzystając z adresu URL przechowywanej rzeczy:
const request = new Request('/my-data-store/item-id');
Praca z obiektami odpowiedzi
Konstruktor obiektów Response
akceptuje wiele typów danych, w tym obiekty Blob
, ArrayBuffer
, FormData
i ciągi tekstowe.
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
Aby ustawić typ MIME Response
, ustaw odpowiedni nagłówek.
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
Jeśli pobrany plik Response
został pobrany i chcesz uzyskać dostęp do jego treści, możesz skorzystać z kilku metod pomocniczych. Każdy z nich zwraca identyfikator Promise
, który zwraca wartość innego typu.
Metoda | Opis |
---|---|
arrayBuffer |
Zwraca obiekt ArrayBuffer zawierający treść zserializowany do bajtów.
|
blob |
Zwraca Blob . Jeśli Response został utworzony za pomocą Blob , nowy Blob ma ten sam typ. W innym przypadku używana jest właściwość Content-Type właściwości Response .
|
text |
Interpretuje bajty treści jako ciąg zakodowany w formacie UTF-8. |
json |
Interpretuje bajty treści jako ciąg zakodowany w formacie UTF-8, a następnie próbuje przeanalizować go jako JSON. Zwraca wynikowy obiekt lub zwraca TypeError , jeśli ciągu znaków nie można przeanalizować jako JSON.
|
formData |
Interpretuje bajty treści jako formularz HTML zakodowany jako multipart/form-data lub application/x-www-form-urlencoded . Zwraca obiekt FormData lub zwraca obiekt TypeError , jeśli nie można przeanalizować danych.
|
body |
Zwraca obiekt ReadableStream dotyczący danych treści. |
Przykład
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]
Pobieram z pamięci podręcznej
Aby znaleźć element w pamięci podręcznej, możesz użyć metody match
.
const response = await cache.match(request);
console.log(request, response);
Jeśli request
jest ciągiem, przeglądarka przekształca go w Request
, wywołując funkcję new Request(request)
. Funkcja zwraca wartość Promise
, która zwraca wartość Response
, jeśli zostanie znaleziony pasujący wpis. W przeciwnym razie zwraca ona wartość undefined
.
Aby określić, czy 2 elementy Requests
pasują, przeglądarka używa więcej niż tylko adresu URL. Dwa żądania są uznawane za różne, jeśli mają różne ciągi zapytań, nagłówki Vary
lub metody HTTP (GET
, POST
, PUT
itp.).
Możesz zignorować niektóre lub wszystkie z tych elementów, przekazując obiekt options jako drugi parametr.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
Jeśli pasuje więcej niż jedno żądanie w pamięci podręcznej, zwracane jest to, które zostało utworzone jako pierwsze. Jeśli chcesz pobrać wszystkie pasujące odpowiedzi, możesz użyć polecenia 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.`);
Możesz szybko przeszukać wszystkie pamięci podręczne jednocześnie, używając funkcji caches.match()
zamiast wywoływać cache.match()
w przypadku każdej pamięci podręcznej.
Szukam
Interfejs Cache API nie umożliwia wyszukiwania żądań ani odpowiedzi z wyjątkiem pasujących wpisów dotyczących obiektu Response
. Możesz jednak wdrożyć własne wyszukiwanie, używając filtrów lub tworząc indeks.
Filtrowanie
Jednym ze sposobów wdrożenia własnego wyszukiwania jest iteracja wszystkich wpisów i odfiltrowanie tych, które są Ci potrzebne. Załóżmy, że chcesz znaleźć wszystkie elementy,
które mają adresy URL kończące się na .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;
}
W ten sposób możesz użyć dowolnej właściwości obiektów Request
i Response
do filtrowania wpisów. Pamiętaj, że to trwa długo, gdy przeszukujesz duże zbiory danych.
Tworzenie indeksu
Innym sposobem implementacji własnego wyszukiwania jest utrzymanie osobnego indeksu wpisów, które można przeszukiwać i przechowywać w IndexedDB. Ponieważ do tego rodzaju operacji została zaprojektowana usługa IndexedDB, działa znacznie lepiej w przypadku dużej liczby wpisów.
Jeśli przechowujesz adres URL obiektu Request
razem z dostępnymi do przeszukiwania właściwościami, po przeprowadzeniu wyszukiwania możesz z łatwością pobrać prawidłowy wpis w pamięci podręcznej.
Usuwanie elementu
Aby usunąć element z pamięci podręcznej:
cache.delete(request);
Gdzie żądanie może być ciągiem znaków Request
lub URL-a. Ta metoda przyjmuje te same obiekty options co cache.match
, co umożliwia usunięcie wielu par Request
/Response
z tego samego adresu URL.
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
Usuwanie pamięci podręcznej
Aby usunąć pamięć podręczną, wywołaj caches.delete(name)
. Ta funkcja zwraca wartość Promise
zwracającą wartość true
, jeśli pamięć podręczna istniała i została usunięta, lub false
w inny sposób.
Dziękujemy
Dziękujemy firmie Mat Scales, która napisała oryginalną wersję tego artykułu, który po raz pierwszy ukazał się w WebFundamentals.