Informationen zum Verwenden der Cache API, um Ihre Anwendungsdaten offline verfügbar zu machen
Die Cache API ist ein System zum Speichern und Abrufen von Netzwerkanfragen und der 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, um unabhängig von der Netzwerkgeschwindigkeit oder -verfügbarkeit schnelle Antworten zu liefern. 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. So können Sie mit einer einfachen Funktionserkennung prüfen, ob die API verfügbar ist:
const cacheAvailable = 'caches' in self;
Der Cache API kann über ein Fenster, einen IFrame, einen Worker oder einen Service Worker zugegriffen werden.
Was kann gespeichert werden?
Die Caches speichern nur Paare von Request
- und Response
-Objekten, die jeweils HTTP-Anfragen und ‑Antworten darstellen. Die Anfragen und Antworten können jedoch jede Art von Daten enthalten, die über HTTP übertragen werden können.
Wie viel kann gespeichert werden?
Kurz gesagt: Sehr viel, mindestens ein paar hundert Megabyte und potenziell Hunderte von Gigabyte oder mehr. Browserimplementierungen variieren, aber die verfügbare Speichermenge basiert in der Regel auf der auf dem Gerät verfügbaren Speichermenge.
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 eine Promise
zurück, die 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 einen Artikel hinzuzufügen: add
, addAll
und put
.
Alle drei Methoden geben eine Promise
zurück.
cache.add
Zuerst ist da cache.add()
. Er nimmt einen Parameter entgegen, 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 der 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()
, nimmt aber ein Array von Request
-Objekten oder URLs (string
s) an. Das funktioniert ähnlich wie der Aufruf von cache.add
für jede einzelne Anfrage, mit der Ausnahme, dass Promise
abgelehnt wird, wenn eine einzelne Anfrage nicht im Cache gespeichert ist.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
In jedem dieser Fälle wird ein übereinstimmender vorhandener Eintrag durch einen neuen Eintrag überschrieben. Dabei werden dieselben Abgleichsregeln verwendet, die im Abschnitt Abrufen beschrieben wurden.
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. Er nimmt zwei Parameter entgegen. Das erste kann entweder ein Request
-Objekt oder eine URL (string
) sein. Das zweite muss ein Response
sein, entweder aus dem Netzwerk oder durch deinen 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 toleranter als add()
oder addAll()
und ermöglicht das Speichern von nicht CORS-Antworten oder anderen Antworten, deren Statuscode nicht im Bereich 200 liegt. Dadurch werden alle vorherigen Antworten für dieselbe Anfrage überschrieben.
Anfrageobjekte erstellen
Erstellen Sie das Request
-Objekt mit einer URL für das gespeicherte Element:
const request = new Request('/my-data-store/item-id');
Mit Antwortobjekten arbeiten
Der Konstruktor des Response
-Objekts akzeptiert viele Datentypen, darunter Blob
, ArrayBuffer
, 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 einer 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 verschiedene Hilfsmethoden verwenden. Jede Funktion gibt eine Promise
zurück, die 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 die Content-Type der Response verwendet.
|
text |
Die Bytes des Body werden als UTF-8-codierter String interpretiert. |
json |
Die Bytes des Body werden als UTF-8-codierter String interpretiert und dann als JSON geparst. Gibt das resultierende Objekt zurück oder wirft eine TypeError , wenn der String nicht als JSON geparst werden kann.
|
formData |
Die Bytes des Textkörpers werden als HTML-Formular interpretiert, das entweder als multipart/form-data oder application/x-www-form-urlencoded codiert ist. Gibt ein FormData-Objekt zurück oder löst einen 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
Wenn Sie ein Element in einem Cache suchen möchten, können Sie die Methode match
verwenden.
const response = await cache.match(request);
console.log(request, response);
Wenn request
ein String ist, wandelt der Browser ihn durch Aufrufen von new Request(request)
in einen Request
um. Die Funktion gibt eine Promise
zurück, die in Response
umgewandelt wird, wenn ein übereinstimmender Eintrag gefunden wird, andernfalls in undefined
.
Um festzustellen, ob zwei Requests
übereinstimmen, verwendet der Browser nicht nur die URL. Zwei Anfragen gelten als unterschiedlich, wenn sie unterschiedliche Suchstrings, Vary
-Header oder HTTP-Methoden (GET
, POST
, PUT
usw.) haben.
Sie können einige oder alle diese Elemente 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 mehrere im Cache gespeicherte Anfragen übereinstimmen, wird diejenige zurückgegeben, die zuerst erstellt wurde. 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.`);
Als Verknüpfung können Sie alle Caches gleichzeitig durchsuchen, indem Sie caches.match()
verwenden, anstatt für jeden Cache cache.match()
aufzurufen.
Suchen
Die Cache API bietet keine Möglichkeit, nach Anfragen oder Antworten zu suchen, es sei denn, Einträge werden mit einem Response
-Objekt abgeglichen. Sie können jedoch eine eigene Suche mithilfe von Filtern oder durch Erstellen eines Index implementieren.
Filtern
Eine Möglichkeit, eine eigene Suche zu implementieren, besteht darin, alle Einträge zu durchlaufen und die gewünschten herauszufiltern. 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;
}
So können Sie beliebige Properties der Objekte Request
und Response
verwenden, um die Einträge zu filtern. Beachten Sie, dass dies bei der Suche in großen Datenmengen langsam ist.
Index erstellen
Die andere Möglichkeit, eine eigene Suche zu implementieren, besteht darin, einen separaten Index von Einträgen zu verwalten, der durchsucht werden kann, und den Index in IndexedDB zu speichern. Da IndexedDB für diese Art von Vorgängen entwickelt wurde, ist die Leistung bei einer großen Anzahl von Einträgen viel besser.
Wenn Sie die URL der Request
zusammen mit den suchbaren Properties speichern, können Sie nach der Suche ganz einfach den richtigen Cache-Eintrag abrufen.
Elemente löschen
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 bei cache.match
verwendet. So können Sie mehrere Request
/Response
-Paare für dieselbe URL löschen.
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
.
Vielen Dank
Vielen Dank an Mat Scales, der die ursprüngliche Version dieses Artikels verfasst hat, die zuerst auf WebFundamentals veröffentlicht wurde.