Interfejs Cache API: krótki przewodnik

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;

Obsługa przeglądarek

  • 40
  • 16
  • 41
  • 11.1

Źródło

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.