Scopri come utilizzare l'API Cache per rendere disponibili offline i dati della tua applicazione.
L'API Cache è un sistema per l'archiviazione e il recupero richieste e le risposte corrispondenti. Potrebbero essere richieste regolari e risposte create durante l'esecuzione dell'applicazione, oppure potrebbero essere creati esclusivamente allo scopo di archiviare i dati per utilizzarli in un secondo momento.
L'API Cache è stata creata per consentire ai service worker di memorizzare nella cache le richieste di rete in modo da poter fornire risposte rapide, indipendentemente dalla velocità della rete la disponibilità del servizio. Tuttavia, l'API può essere utilizzata anche come meccanismo generale di archiviazione.
Dove è disponibile?
L'API Cache è disponibile in tutti i browser moderni. È
esposto tramite la proprietà globale caches
, per consentirti di testare la presenza di
l'API con un semplice rilevamento delle caratteristiche:
const cacheAvailable = 'caches' in self;
È possibile accedere all'API Cache da una finestra, un iframe, un worker o un service worker.
Elementi archiviabili
Le cache archiviano solo le coppie di Request
e
oggetti Response
, che rappresentano richieste e risposte HTTP.
rispettivamente. Tuttavia, le richieste e le risposte possono contenere qualsiasi tipo di dati
che possono essere trasferiti tramite HTTP.
Quanti dati si possono memorizzare?
In breve, molti, almeno un paio di centinaia di megabyte e potenzialmente centinaia di gigabyte o più. Le implementazioni dei browser variano, ma la quantità di spazio di archiviazione disponibile si basa in genere sulla quantità di spazio di archiviazione disponibile del dispositivo.
Creazione e apertura di una cache
Per aprire una cache, utilizza il metodo caches.open(name)
, passando il nome del metodo
Cache come singolo parametro. Se la cache denominata non esiste,
è stato creato. Questo metodo restituisce un Promise
che si risolve con l'oggetto Cache
.
const cache = await caches.open('my-cache');
// do something with cache...
Aggiunta a una cache in corso...
Esistono tre modi per aggiungere un elemento a una cache: add
, addAll
e put
.
Tutti e tre i metodi restituiscono un valore Promise
.
cache.add
Innanzitutto, le sono cache.add()
. Può essere richiesto un solo parametro, Request
o un URL (string
). Invia una richiesta alla rete e archivia la risposta
nella cache. Se
il recupero non va a buon fine o se il codice di stato della risposta non è compreso nell'intervallo dei 200,
non viene memorizzato nulla e Promise
viene rifiutato. Tieni presente che
le richieste non in modalità CORS non possono essere archiviate perché restituiscono un valore status
di
0
. Queste richieste possono essere archiviate solo con 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
Poi c'è cache.addAll()
. Funziona in modo simile a add()
, ma richiede una
array di Request
oggetti o URL (string
). Funziona in modo simile a
chiamata cache.add
per ogni singola richiesta, tranne che per Promise
rifiuta se una singola richiesta non viene memorizzata nella cache.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
In ognuno di questi casi, una nuova voce sovrascrive qualsiasi voce esistente corrispondente. Vengono utilizzate le stesse regole di corrispondenza descritte nella sezione recupero in corso.
cache.put
Infine, c'è cache.put()
, che ti consente di archiviare una risposta
dalla rete oppure creare e archiviare il tuo Response
. Sono necessari due
parametri. Il primo può essere un oggetto Request
o un URL (string
).
Il secondo deve essere un Response
, proveniente dalla rete o generato dal tuo
le API nel tuo codice.
// 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');
Il metodo put()
è più permissivo di add()
o addAll()
e
potrai archiviare le risposte non CORS o altre risposte il cui stato
del codice della risposta non è compreso nell'intervallo dei 200. Sovrascriverà eventuali modifiche precedenti
risposte per la stessa richiesta.
Creazione di oggetti di richiesta
Crea l'oggetto Request
utilizzando un URL per l'elemento da archiviare:
const request = new Request('/my-data-store/item-id');
Utilizzo degli oggetti Response
Il costruttore di oggetti Response
accetta molti tipi di dati, tra cui
oggetti Blob
, ArrayBuffer
s, FormData
e stringhe.
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
Puoi impostare il tipo MIME di Response
impostando l'intestazione appropriata.
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
Se hai recuperato un Response
e vuoi accedere al relativo corpo,
diversi metodi helper che puoi usare. Ciascuno restituisce un Promise
che si risolve
con un valore di tipo diverso.
Metodo | Descrizione |
---|---|
arrayBuffer |
Restituisce un oggetto ArrayBuffer contenente il corpo, serializzato su
byte.
|
blob |
Restituisce un Blob . Se Response è stato creato
con Blob , il nuovo Blob ha lo stesso
di testo. In caso contrario, i valori Content-Type del
È in uso Response .
|
text |
Interpreta i byte del corpo come stringa con codifica UTF-8. |
json |
Interpreta i byte del corpo come stringa con codifica UTF-8, quindi prova
per analizzarlo come JSON. Restituisce l'oggetto risultante o genera un
TypeError se la stringa non può essere analizzata come JSON.
|
formData |
Interpreta i byte del corpo come un modulo HTML, codificato come
multipart/form-data o
application/x-www-form-urlencoded . Restituisce un
FormData
oppure genera un TypeError se non è possibile analizzare i dati.
|
body |
Restituisce un oggetto ReadableStream per i dati del corpo. |
Ad esempio:
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]
Recupero da una cache
Per trovare un elemento in una cache, puoi usare il metodo match
.
const response = await cache.match(request);
console.log(request, response);
Se request
è una stringa, il browser la converte in Request
richiamando
new Request(request)
. La funzione restituisce un Promise
che si risolve in
Response
, se viene trovata una voce corrispondente, o undefined
, altrimenti.
Per determinare se due Requests
corrispondono, il browser non si limita a utilizzare l'URL. Due.
vengono considerate diverse se hanno stringhe di query differenti,
Intestazioni Vary
o metodi HTTP (GET
, POST
, PUT
e così via).
Puoi ignorare alcuni di questi aspetti o tutti passando un oggetto options sotto forma di secondo parametro.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
Se più di una richiesta memorizzata nella cache corrisponde, quella creata per prima
restituito. Se vuoi recuperare tutte le risposte corrispondenti, puoi utilizzare
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.`);
Come scorciatoia puoi cercare in tutte le cache contemporaneamente utilizzando caches.match()
anziché chiamare cache.match()
per ogni cache.
Ricerca in corso
L'API Cache non fornisce un modo per cercare richieste o risposte
tranne le voci corrispondenti a un oggetto Response
. Tuttavia, puoi
implementare la tua ricerca usando i filtri o creando un indice.
Filtri
Un modo per implementare la propria ricerca è eseguire l'iterazione di tutte le voci e
filtra per visualizzare quelli che preferisci. Supponiamo di voler trovare tutte
elementi che hanno URL che terminano con .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;
}
In questo modo puoi utilizzare qualsiasi proprietà degli oggetti Request
e Response
per
filtrando le voci. Tieni presente che l'operazione risulta lenta se cerchi grandi insiemi di
e i dati di Google Cloud.
Creazione di un indice
L'altro modo per implementare la tua ricerca è mantenere un indice separato di voci in cui è possibile eseguire ricerche e archiviano l'indice in IndexedDB. Poiché questo è il tipo di per cui è stato progettato IndexedDB ha prestazioni molto migliori con un numero elevato di voci.
Se memorizzi l'URL di Request
insieme alle proprietà disponibili per la ricerca
puoi recuperare facilmente la voce corretta della cache dopo aver eseguito la ricerca.
Eliminazione di un elemento
Per eliminare un elemento da una cache:
cache.delete(request);
Dove la richiesta può essere un Request
o una stringa URL. Questo metodo utilizza anche
stesso oggetto opzioni di cache.match
, che ti consente di eliminare più
Request
/Response
coppie per lo stesso URL.
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
Eliminazione di una cache
Per svuotare una cache, chiama caches.delete(name)
. Questa funzione restituisce un
Promise
che si risolve in true
se la cache esisteva ed è stata eliminata oppure
false
negli altri casi.
Grazie
Grazie a Mat Scales, che ha scritto la versione originale di questo articolo, che su WebFundamentals.