Saiba como usar a API Cache para disponibilizar os dados do seu aplicativo off-line.
A API Cache é um sistema para armazenar e recuperar e as respostas correspondentes. Podem ser solicitações regulares e as respostas criadas durante a execução do aplicativo, ou podem ser criados exclusivamente com o propósito de armazenar dados para uso posterior.
A API Cache foi criada para permitir que os service workers armazenem em cache as solicitações de rede para que possam fornecer respostas rápidas, independentemente da velocidade da rede ou disponibilidade. No entanto, a API também pode ser usada como um mecanismo geral de armazenamento.
Onde ele está disponível?
A API Cache está disponível em todos os navegadores modernos. É
exposto pela propriedade caches
global, para que você possa testar a presença de
a API com uma detecção de recursos simples:
const cacheAvailable = 'caches' in self;
A API Cache pode ser acessada em uma janela, iframe, worker ou service worker.
O que pode ser armazenado
Os caches armazenam apenas pares de Request
e
Objetos Response
, que representam solicitações e respostas HTTP,
respectivamente. No entanto, as solicitações e respostas podem conter qualquer tipo de dados
que podem ser transferidos por HTTP.
Quantos dados podem ser armazenados?
Resumindo, muitos, pelo menos algumas centenas de megabytes e potencialmente centenas de gigabytes ou mais. As implementações dos navegadores variam, mas a quantidade de armazenamento disponível geralmente se baseia na quantidade de armazenamento o dispositivo.
Como criar e abrir um cache
Para abrir um cache, use o método caches.open(name)
, transmitindo o nome do
cache como parâmetro único. Se o cache nomeado não existe, é
criados. Esse método retorna um Promise
que é resolvido com o objeto Cache
.
const cache = await caches.open('my-cache');
// do something with cache...
Como adicionar a um cache
Há três maneiras de adicionar um item a um cache: add
, addAll
e put
.
Todos os três métodos retornam um Promise
.
cache.add
Primeiro, há cache.add()
. Ele utiliza um parâmetro, seja um Request
.
ou um URL (string
). Ele faz uma solicitação à rede e armazena a resposta
no cache. Se o
a busca falhar, ou se o código de status da resposta não estiver no intervalo 200,
nada será armazenado, e o Promise
será rejeitado. Os dados de origem cruzada
solicitações fora do modo CORS não podem ser armazenadas porque retornam um status
de
0
. Essas solicitações só podem ser armazenadas com 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
Em seguida, temos cache.addAll()
. Funciona de forma semelhante a add()
, mas usa uma
matriz de objetos Request
ou URLs (string
s). Isso funciona de forma semelhante
chamando cache.add
para cada solicitação individual, exceto pelo fato de que Promise
será rejeitada se uma única solicitação não estiver armazenada em cache.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
Em cada um desses casos, uma nova entrada substitui qualquer entrada correspondente. Isso usa as mesmas regras de correspondência descritas na seção recuperando.
cache.put
Por fim, há cache.put()
, que permite armazenar uma resposta
da rede ou crie e armazene seus próprios Response
. São necessárias duas
parâmetros. O primeiro pode ser um objeto Request
ou um URL (string
).
O segundo precisa ser um Response
da rede ou gerado pelo seu
o código-fonte.
// 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');
O método put()
é mais permissivo do que add()
ou addAll()
, e
permitem armazenar respostas não CORS ou outras respostas em que o status
da resposta não está no intervalo 200. Ele substituirá
para a mesma solicitação.
Como criar objetos de solicitação
Crie o objeto Request
usando um URL para o item que está sendo armazenado:
const request = new Request('/my-data-store/item-id');
Como trabalhar com objetos de resposta
O construtor do objeto Response
aceita muitos tipos de dados, incluindo
Blob
s, ArrayBuffer
s, objetos FormData
e strings.
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
Para definir o tipo MIME de uma Response
, defina o cabeçalho adequado.
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
Se você recuperou um Response
e quer acessar o corpo dele, há
vários métodos auxiliares que podem ser usados. Cada um retorna um Promise
que resolve
com um valor de um tipo diferente.
Método | Descrição |
---|---|
arrayBuffer |
Retorna um ArrayBuffer contendo o corpo, serializado para
bytes.
|
blob |
Retorna um Blob . Se o Response tiver sido criado
com um Blob , então esse novo Blob terá o mesmo
não é válido. Caso contrário, o Content-Type do
Response é usado.
|
text |
Interpreta os bytes do corpo como uma string codificada em UTF-8. |
json |
Interpreta os bytes do corpo como uma string codificada em UTF-8 e tenta
para analisá-lo como JSON. Retorna o objeto resultante ou gera uma
TypeError se a string não puder ser analisada como JSON.
|
formData |
Interpreta os bytes do corpo como um formulário HTML, codificado como
multipart/form-data ou
application/x-www-form-urlencoded . Retorna um
FormData
ou gera uma TypeError se os dados não puderem ser analisados.
|
body |
Retorna um ReadableStream para os dados do corpo. |
Por exemplo:
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]
Como recuperar de um cache
Para encontrar um item em um cache, use o método match
.
const response = await cache.match(request);
console.log(request, response);
Se request
for uma string, o navegador a converterá em uma Request
chamando
new Request(request)
A função retorna um Promise
que é resolvido como
um Response
se uma entrada correspondente for encontrada; caso contrário, undefined
.
Para determinar se dois Requests
são correspondentes, o navegador usa mais do que apenas o URL. Duas
as solicitações são consideradas diferentes
se têm strings de consulta diferentes,
cabeçalhos Vary
ou métodos HTTP (GET
, POST
, PUT
etc.).
Você pode ignorar alguns ou todos esses itens passando um objeto de opções como um segundo parâmetro.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
Se houver correspondência de mais de uma solicitação em cache, aquela que foi criada primeiro será
retornados. Se quiser recuperar todas as respostas correspondentes, você poderá 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 atalho, você pode pesquisar em todos os caches de uma só vez usando caches.match()
.
em vez de chamar cache.match()
para cada cache.
Pesquisando…
A API Cache não fornece uma maneira de pesquisar solicitações ou respostas
exceto para entradas correspondentes a um objeto Response
. No entanto, é possível
implementar sua própria pesquisa usando filtros ou criando um índice.
Filtragem
Uma forma de implementar sua própria pesquisa é iterar em todas as entradas e
e filtre pelos que você quer. Digamos que você queira encontrar todos
itens com URLs terminados em .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;
}
Dessa forma, é possível usar qualquer propriedade dos objetos Request
e Response
para
filtrar as entradas. Esse processo é lento quando você pesquisa em grandes conjuntos de
dados.
Como criar um índice
A outra maneira de implementar sua própria pesquisa é manter um índice separado de entradas que podem ser pesquisadas e armazenar o índice no IndexedDB. Como este é o tipo de operação para a qual o IndexedDB foi projetado, tem um desempenho muito melhor um grande número de entradas.
Se você armazenar o URL do Request
com as propriedades pesquisáveis
você poderá recuperar facilmente a entrada correta no cache depois de fazer a pesquisa.
Como excluir um item
Para excluir um item de um cache:
cache.delete(request);
Em que a solicitação pode ser Request
ou uma string de URL. Esse método também recebe
mesmo objeto de opções de cache.match
, que permite excluir várias
Request
/Response
para o mesmo URL.
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
Como excluir um cache
Para excluir um cache, chame caches.delete(name)
. Essa função retorna uma
Promise
, que é resolvido como true
se o cache existia e foi excluído; ou
Caso contrário, false
.
Obrigado
Agradecemos a Mat Scales, que escreveu a versão original deste artigo, apareceu pela primeira vez no WebFundamentals.