Die Cache API: Eine Kurzanleitung

Erfahren Sie, wie Sie mit der Cache API Anwendungsdaten offline verfügbar machen.

Die Cache API ist ein System zum Speichern und Abrufen von Netzwerkanfragen und den zugehörigen Antworten. Dabei kann es sich um normale Anfragen und Antworten handeln, die während der Ausführung Ihrer Anwendung erstellt werden. Sie können aber auch ausschließlich zum Speichern von Daten für die spätere Verwendung erstellt werden.

Die Cache API wurde entwickelt, damit Service Worker Netzwerkanfragen im Cache speichern können, sodass sie unabhängig von der Netzwerkgeschwindigkeit oder -verfügbarkeit schnelle Antworten liefern können. Die API kann jedoch auch als allgemeiner Speichermechanismus verwendet werden.

Wo ist der Dienst verfügbar?

Die Cache API ist in allen modernen Browsern verfügbar. Sie wird über das globale Attribut caches bereitgestellt, sodass Sie das Vorhandensein der API mit einer einfachen Funktionserkennung prüfen können:

const cacheAvailable = 'caches' in self;

Unterstützte Browser

  • 40
  • 16
  • 41
  • 11.1

Quelle

Auf die Cache API kann über ein Fenster, einen iFrame, einen Worker oder einen Service Worker zugegriffen werden.

Was kann gespeichert werden?

In den Caches werden nur Paare von Request- und Response-Objekten gespeichert, die jeweils HTTP-Anfragen und -Antworten darstellen. Die Anfragen und Antworten können jedoch beliebige Daten enthalten, die über HTTP übertragen werden können.

Wie viel kann ich speichern?

Kurz gesagt: eine Menge, mindestens ein paar hundert Megabyte und potenziell mehrere Hundert Gigabyte oder mehr. Browserimplementierungen variieren, aber die Größe des verfügbaren Speichers hängt in der Regel vom verfügbaren Speicher auf dem Gerät ab.

Cache erstellen und öffnen

Verwenden Sie zum Öffnen eines Cache die Methode caches.open(name) und übergeben Sie den Namen des Cache als einzelnen Parameter. Wenn der benannte Cache nicht vorhanden ist, wird er erstellt. Diese Methode gibt ein Promise zurück, das mit dem Cache-Objekt aufgelöst wird.

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

Zu einem Cache hinzufügen

Es gibt drei Möglichkeiten, einem Cache ein Element hinzuzufügen: add, addAll und put. Alle drei Methoden geben ein Promise zurück.

cache.add

Erstens: cache.add(). Sie verwendet einen Parameter, entweder einen Request oder eine URL (string). Er sendet eine Anfrage an das Netzwerk und speichert die Antwort im Cache. Wenn der Abruf fehlschlägt oder der Statuscode der Antwort nicht im Bereich 200 liegt, wird nichts gespeichert und Promise wird abgelehnt. Ursprungsübergreifende Anfragen, die nicht im CORS-Modus sind, können nicht gespeichert werden, da sie als status den Wert 0 zurückgeben. Solche Anfragen können nur mit put gespeichert werden.

// 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

Als Nächstes kommt cache.addAll(). Sie funktioniert ähnlich wie add(), verwendet aber ein Array von Request-Objekten oder URLs (strings). Das funktioniert ähnlich wie das Aufrufen von cache.add für jede einzelne Anfrage, mit der Ausnahme, dass Promise abgelehnt wird, wenn keine einzelne Anfrage im Cache gespeichert wird.

const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);

In jedem dieser Fälle überschreibt ein neuer Eintrag alle übereinstimmenden vorhandenen Einträge. Dabei werden dieselben Abgleichsregeln verwendet, die im Abschnitt retrieving beschrieben sind.

cache.put

Schließlich gibt es noch cache.put(), mit dem Sie entweder eine Antwort aus dem Netzwerk speichern oder Ihre eigene Response erstellen und speichern können. Es sind zwei Parameter erforderlich. Die erste kann entweder ein Request-Objekt oder eine URL (string) sein. Die zweite muss eine Response sein, entweder aus dem Netzwerk oder von Ihrem Code generiert.

// 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');

Die Methode put() ist großzügiger als add() oder addAll(). Sie ermöglicht es Ihnen, Nicht-CORS-Antworten oder andere Antworten zu speichern, bei denen der Statuscode der Antwort nicht im Bereich 200 liegt. Dadurch werden alle vorherigen Antworten für dieselbe Anfrage überschrieben.

Anfrageobjekte erstellen

Erstellen Sie das Request-Objekt unter Verwendung einer URL für das zu speichernde Objekt:

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

Mit Antwortobjekten arbeiten

Der Response-Objektkonstruktor akzeptiert viele Datentypen, darunter Blobs, ArrayBuffers, FormData-Objekte und Strings.

const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');

Sie können den MIME-Typ eines Response festlegen, indem Sie den entsprechenden Header festlegen.

  const options = {
    headers: {
      'Content-Type': 'application/json'
    }
  }
  const jsonResponse = new Response('{}', options);

Wenn Sie eine Response abgerufen haben und auf ihren Text zugreifen möchten, können Sie mehrere Hilfsmethoden verwenden. Jede gibt einen Promise zurück, der in einen Wert eines anderen Typs aufgelöst wird.

Methode Beschreibung
arrayBuffer Gibt ein ArrayBuffer zurück, das den Text enthält, serialisiert in Byte.
blob Gibt Blob zurück. Wenn die Response mit einer Blob erstellt wurde, hat diese neue Blob denselben Typ. Andernfalls wird der Content-Type von Response verwendet.
text Interpretiert die Byte des Textkörpers als UTF-8-codierten String.
json Interpretiert die Byte des Texts als UTF-8-codierten String und versucht dann, ihn als JSON zu parsen. Gibt das resultierende Objekt zurück oder löst einen TypeError aus, wenn der String nicht als JSON geparst werden kann.
formData Interpretiert die Byte des Textkörpers als HTML-Formular, das entweder als multipart/form-data oder application/x-www-form-urlencoded codiert ist. Gibt ein FormData-Objekt zurück oder löst eine TypeError aus, wenn die Daten nicht geparst werden können.
body Gibt einen ReadableStream für die Textdaten zurück.

Beispiel:

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]

Daten aus einem Cache abrufen

Mit der Methode match können Sie ein Element in einem Cache suchen.

const response = await cache.match(request);
console.log(request, response);

Wenn request ein String ist, konvertiert der Browser ihn durch Aufrufen von new Request(request) in eine Request. Die Funktion gibt ein Promise zurück, das in einen Response aufgelöst wird, wenn ein übereinstimmender Eintrag gefunden wird, oder in undefined.

Um festzustellen, ob zwei Requests übereinstimmen, verwendet der Browser nicht nur die URL. Zwei Anfragen gelten als unterschiedlich, wenn sie unterschiedliche Abfragestrings, Vary-Header oder HTTP-Methoden (GET, POST, PUT usw.) haben.

Sie können einige oder alle dieser Dinge ignorieren, indem Sie ein Optionsobjekt als zweiten Parameter übergeben.

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

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

Wenn mehr als eine im Cache gespeicherte Anfrage übereinstimmt, wird die zuerst erstellte Anfrage zurückgegeben. Wenn Sie alle übereinstimmenden Antworten abrufen möchten, können Sie cache.matchAll() verwenden.

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

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

Außerdem können Sie in allen Caches gleichzeitig suchen, indem Sie caches.match() verwenden, anstatt cache.match() für jeden Cache aufzurufen.

Suchen

Die Cache API bietet keine Möglichkeit, nach Anfragen oder Antworten zu suchen, es sei denn, es werden übereinstimmende Einträge mit einem Response-Objekt gefunden. Sie können jedoch Ihre eigene Suche mithilfe von Filtern oder durch Erstellen eines Index implementieren.

Wird gefiltert

Eine Möglichkeit, Ihre eigene Suche zu implementieren, besteht darin, über alle Einträge zu iterieren und nach den gewünschten Einträgen zu filtern. Angenommen, Sie möchten alle Elemente finden, deren URLs auf .png enden.

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;
}

Auf diese Weise können Sie ein beliebiges Attribut der Request- und Response-Objekte zum Filtern der Einträge verwenden. Beachten Sie, dass dies langsam ist, wenn Sie in großen Datenmengen suchen.

Index erstellen

Die andere Möglichkeit, Ihre eigene Suche zu implementieren, besteht darin, einen separaten Index mit Einträgen zu verwalten, die durchsucht werden können, und den Index in IndexedDB zu speichern. Da IndexedDB für diesen Vorgang konzipiert wurde, erzielt er bei einer großen Anzahl von Einträgen eine viel bessere Leistung.

Wenn Sie die URL von Request zusammen mit den durchsuchbaren Attributen speichern, können Sie nach der Suche einfach den richtigen Cache-Eintrag abrufen.

Löschen von Elementen

So löschen Sie ein Element aus einem Cache:

cache.delete(request);

Dabei kann die Anfrage ein Request- oder URL-String sein. Bei dieser Methode wird auch dasselbe Optionsobjekt wie cache.match verwendet, sodass du mehrere Request/Response-Paare für dieselbe URL löschen kannst.

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

Cache löschen

Rufen Sie caches.delete(name) auf, um einen Cache zu löschen. Diese Funktion gibt ein Promise zurück, das in true aufgelöst wird, wenn der Cache vorhanden war und gelöscht wurde, oder false.

Danke

Vielen Dank an Mat Scales, der die Originalversion dieses Artikels verfasst hat, die erstmals auf WebFundamentals erschienen ist.