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. Dies können normale Anfragen und Antworten sein, die beim Ausführen Ihrer Anwendung erstellt wurden, oder sie können 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
Wenn Sie einen Cache öffnen möchten, verwenden Sie die Methode caches.open(name)
und geben Sie den Namen des Caches als einzigen Parameter an. 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()
. 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 der Promise
wird abgelehnt. Anfragen zwischen verschiedenen Ursprüngen, die nicht im CORS-Modus sind, können nicht gespeichert werden, da sie einen status
von 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 überschreibt ein neuer Eintrag alle übereinstimmenden vorhandenen Einträge. Dabei werden dieselben Abgleichsregeln verwendet, die im Abschnitt Abrufen beschrieben wurden.
cache.put
Schließlich gibt es cache.put()
, mit dem Sie entweder eine Antwort aus dem Netzwerk speichern oder eine eigene Response
erstellen und speichern können. Es sind zwei Parameter erforderlich. 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 Response
-Objektkonstruktor akzeptiert viele Datentypen, darunter Blob
s, ArrayBuffer
s, 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 mit dem Text zurück, das in Bytes serialisiert ist.
|
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, konvertiert der Browser ihn durch Aufrufen von new Request(request)
in eine Request
. 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 Abfragestrings, 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 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.`);
Sie können aber auch 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 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 langsam ist, wenn Sie in großen Datenmengen suchen.
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 „request“ ein Request
- oder ein 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 einen Promise
zurück, der in true
aufgelöst wird, wenn der Cache vorhanden war und gelöscht wurde, andernfalls in false
.
Vielen Dank
Vielen Dank an Mat Scales, der die ursprüngliche Version dieses Artikels verfasst hat, die zuerst auf WebFundamentals veröffentlicht wurde.