Aprende a usar la API de Cache para que los datos de tu aplicación estén disponibles sin conexión.
La API de Cache es un sistema para almacenar y recuperar datos y sus respuestas correspondientes. Pueden ser solicitudes normales y respuestas creadas durante la ejecución de tu aplicación crearse con el único propósito de almacenar datos para su uso posterior.
La API de Cache se creó para permitir que los service workers almacenen en caché las solicitudes de red para que puedan proporcionar respuestas rápidas, independientemente de la velocidad de la red o disponibilidad. Sin embargo, la API también se puede usar como mecanismo de almacenamiento general.
¿En qué dispositivos está disponible?
La API de Cache está disponible en todos los navegadores actualizados. Sí
que se exponen a través de la propiedad global caches
, de modo que puedas probar la presencia de
la API con una detección de funciones sencilla:
const cacheAvailable = 'caches' in self;
Se puede acceder a la API de Cache desde una ventana, un iframe, un trabajador o un service worker.
Qué se puede almacenar
Las cachés solo almacenan pares de Request
y
objetos Response
, que representan solicitudes y respuestas HTTP.
respectivamente. Sin embargo, las solicitudes y respuestas pueden contener cualquier tipo de datos
que se pueden transferir a través de HTTP.
¿Cuánto se puede almacenar?
En resumen, mucho, al menos un par de cientos de megabytes y, posiblemente, cientos de gigabytes o más. Las implementaciones del navegador varían, pero la cantidad de almacenamiento disponible suele basarse en la cantidad de almacenamiento disponible el dispositivo.
Crea y abre una caché
Para abrir una caché, usa el método caches.open(name)
y pasa el nombre de la
en caché como único parámetro. Si la caché con nombre no existe, se
crear. Este método muestra un Promise
que se resuelve con el objeto Cache
.
const cache = await caches.open('my-cache');
// do something with cache...
Agregar a una caché
Existen tres maneras de agregar un elemento a una caché: add
, addAll
y put
.
Los tres métodos muestran una Promise
.
cache.add
En primer lugar, tenemos cache.add()
. Toma un parámetro, ya sea un Request
.
o una URL (string
). Realiza una solicitud a la red y almacena la respuesta
en la caché. Si el botón
falla la recuperación o si el código de estado de la respuesta no está en el rango 200
no se almacena nada, y Promise
se rechaza. Ten en cuenta que los datos de origen cruzado
las solicitudes que no están en modo CORS no se pueden almacenar porque muestran un status
de
0
Estas solicitudes solo se pueden almacenar 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
A continuación, tenemos el elemento cache.addAll()
. Funciona de manera similar a add()
, pero toma un
array de objetos Request
o URLs (string
) Esto funciona de manera similar
llamando a cache.add
para cada solicitud individual, excepto que Promise
rechaza si alguna solicitud no se almacena en caché.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
En cada uno de estos casos, una entrada nueva reemplaza a cualquier entrada existente que coincida. Esto usa las mismas reglas de coincidencia descritas en la sección sobre recuperar.
cache.put
Por último, está cache.put()
, que te permite almacenar una respuesta
desde la red, o crea y almacena tu propio Response
. Lleva dos
parámetros. El primero puede ser un objeto Request
o una URL (string
).
El segundo debe ser un Response
, ya sea de la red o generado por tu
código.
// 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');
El método put()
es más permisivo que add()
o addAll()
.
te permitirá almacenar respuestas que no son CORS u otras respuestas en las que el estado
de la respuesta no está en el rango de 200. Reemplazará cualquier archivo anterior
para la misma solicitud.
Crea objetos Request
Crea el objeto Request
con una URL para el elemento que se almacenará:
const request = new Request('/my-data-store/item-id');
Trabaja con objetos Response
El constructor de objetos Response
acepta muchos tipos de datos, como los siguientes:
Blob
, ArrayBuffer
, objetos FormData
y cadenas.
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
Puedes configurar el tipo de MIME de un Response
si configuras el encabezado adecuado.
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
Si recuperaste un Response
y deseas acceder a su cuerpo, hay
varios métodos auxiliares que puedes utilizar. Cada uno muestra un Promise
que resuelve
con un valor de un tipo diferente.
Método | Descripción |
---|---|
arrayBuffer |
Muestra un ArrayBuffer que contiene el cuerpo, serializado en
bytes.
|
blob |
Muestra un objeto Blob . Si se creó Response
con un Blob , este nuevo Blob tendrá el mismo
el tipo de letra. De lo contrario, el valor Content-Type de la
Response está en uso.
|
text |
Interpreta los bytes del cuerpo como una string codificada en UTF-8. |
json |
Interpreta los bytes del cuerpo como una cadena codificada en UTF-8 y, luego, intenta
para analizarlo como JSON. Devuelve el objeto resultante o arroja un
TypeError si la cadena no se puede analizar como JSON.
|
formData |
Interpreta los bytes del cuerpo como un formulario HTML, codificados como
multipart/form-data o
application/x-www-form-urlencoded Devuelve un
FormData
objeto, o lanza una TypeError si los datos no se pueden analizar.
|
body |
Muestra un ReadableStream. para los datos del cuerpo. |
Por ejemplo:
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]
Cómo recuperar datos de una caché
Para encontrar un elemento en una caché, puedes usar el método match
.
const response = await cache.match(request);
console.log(request, response);
Si request
es una cadena, el navegador lo convierte en Request
llamando
new Request(request)
La función muestra un Promise
que se resuelve como
una Response
si se encuentra una entrada coincidente; de lo contrario, una undefined
.
Para determinar si dos Requests
coinciden, el navegador usa más que solo la URL. Dos
las solicitudes se consideran diferentes
si tienen diferentes cadenas de consulta,
Encabezados Vary
o métodos HTTP (GET
, POST
, PUT
, etc.).
Puedes ignorar algunos o todos estos elementos pasando un objeto de opciones como segundo parámetro.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
Si más de una solicitud almacenada en caché coincide, entonces la que se creó primero es
que se devuelven. Si quieres recuperar todas las respuestas coincidentes, puedes usar
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.`);
Como acceso directo, puedes buscar en todas las cachés a la vez con caches.match()
.
en lugar de llamar a cache.match()
para cada caché.
Buscando
La API de Cache no proporciona una forma de buscar solicitudes o respuestas
excepto las entradas coincidentes con un objeto Response
. Sin embargo, puedes
implementar tu propia búsqueda usando filtros o creando un índice.
Filtros
Una forma de implementar tu propia búsqueda es iterar en todas las entradas y
filtra según los que desees. Digamos que quieres encontrar
elementos que tienen URL que terminan en .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;
}
De esta manera, puedes usar cualquier propiedad de los objetos Request
y Response
para
filtrar las entradas. Ten en cuenta que este proceso es lento si buscas en grandes conjuntos
de datos no estructurados.
Crea un índice
Otra forma de implementar tu propia búsqueda es mantener un índice separado de en las que se pueden realizar búsquedas y almacenan el índice en IndexedDB. Como este es el tipo de para la que se diseñó IndexedDB tiene un rendimiento mucho mejor con una gran cantidad de entradas.
Si almacenas la URL de Request
junto con las propiedades que se pueden buscar
Luego de realizar la búsqueda, podrás recuperar fácilmente la entrada de caché correcta.
Eliminación de un elemento
Para borrar un elemento de una caché:
cache.delete(request);
Donde la solicitud puede ser una Request
o una cadena de URL. Este método también toma la
mismo objeto de opciones que cache.match
, que te permite borrar varios
Pares Request
/Response
para la misma URL.
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
Borra una caché
Para borrar una caché, llama a caches.delete(name)
. Esta función muestra un
Promise
que se resuelve como true
si la caché existía y se borró, o
De lo contrario, false
.
Gracias
Gracias a Mat Scales, quien escribió la versión original de este artículo, que apareció por primera vez en WebFundamentals.