API Cache: guide rapide

Découvrez comment utiliser l'API Cache pour rendre les données de vos applications disponibles hors connexion.

L'API Cache est un système de stockage et de récupération de requêtes et les réponses correspondantes. Il peut s'agir de requêtes standards et des réponses créées au cours de l'exécution de votre application, être créées uniquement dans le but de stocker des données pour une utilisation ultérieure.

L'API Cache a été créée pour permettre aux service workers de mettre en cache les requêtes réseau afin de fournir des réponses rapides, quel que soit le débit du réseau ou la disponibilité. Cependant, l'API peut également servir de mécanisme de stockage général.

Où ce service est-il disponible ?

L'API Cache est disponible dans tous les navigateurs récents. Il est exposées via la propriété globale caches. Vous pouvez ainsi tester la présence l'API avec une simple détection de caractéristiques:

const cacheAvailable = 'caches' in self;

Navigateurs pris en charge

  • Chrome: 40 <ph type="x-smartling-placeholder">
  • Edge: 16 <ph type="x-smartling-placeholder">
  • Firefox: 41 <ph type="x-smartling-placeholder">
  • Safari: 11.1. <ph type="x-smartling-placeholder">

Source

L'API Cache est accessible depuis une fenêtre, un iFrame, un worker ou un service worker.

Que peut-on stocker ?

Les caches ne stockent que les paires de Request et des objets Response, représentant des requêtes et réponses HTTP, respectivement. Cependant, les requêtes et les réponses peuvent contenir tout type de données transférables via HTTP.

Quelle quantité peut être stockée ?

En bref, beaucoup, au moins quelques centaines de mégaoctets, et potentiellement des centaines de gigaoctets ou plus. Les implémentations de navigateur varient, mais la quantité disponible est généralement basé sur l'espace de stockage disponible l'appareil.

Créer et ouvrir un cache

Pour ouvrir un cache, utilisez la méthode caches.open(name), en transmettant le nom du cache comme paramètre unique. Si le cache nommé n'existe pas, il est créé. Cette méthode renvoie un Promise qui se résout avec l'objet Cache.

const cache = await caches.open('my-cache');
// do something with cache...

Ajout à un cache

Il existe trois façons d'ajouter un élément à un cache : add, addAll et put. Les trois méthodes renvoient un Promise.

cache.add

Tout d'abord, il y a cache.add(). Elle accepte un seul paramètre : un Request ou une URL (string). Il envoie une requête au réseau et stocke la réponse dans le cache. Si le ou si le code d'état de la réponse n'est pas compris dans la plage 200, alors rien n'est stocké, et Promise le rejette. Notez que les données multi-origines les requêtes qui ne sont pas en mode CORS ne peuvent pas être stockées, car elles renvoient un status 0 Ces requêtes ne peuvent être stockées qu'avec 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

Ensuite, il y a cache.addAll(). Son fonctionnement est semblable à celui de add(), mais il prend une Tableau d'objets Request ou d'URL (string). Ce fonctionnement est semblable à en appelant cache.add pour chaque requête individuelle, sauf que Promise rejette si une requête unique n'est pas mise en cache.

const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);

Dans chacun de ces cas, une nouvelle entrée remplace toute entrée correspondante existante. Les règles de correspondance sont les mêmes que celles décrites dans la section la récupération.

cache.put

Enfin, cache.put(), qui vous permet de stocker une réponse à partir du réseau, ou créer et stocker vos propres Response. Il faut deux paramètres. Le premier peut être un objet Request ou une URL (string). Le second doit être un Response, issu du réseau ou généré par votre du code source.

// 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');

La méthode put() est plus permissive que add() ou addAll(). vous permet de stocker des réponses autres que CORS, ou d'autres réponses dont l'état code de réponse n'est pas compris dans la plage 200. Elle écrasera les éventuelles pour la même demande.

Créer des objets Request

Créez l'objet Request à l'aide d'une URL pour l'élément stocké:

const request = new Request('/my-data-store/item-id');

Utiliser des objets Response

Le constructeur d'objet Response accepte de nombreux types de données, y compris Blob, ArrayBuffer, objets FormData et chaînes.

const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');

Vous pouvez définir le type MIME d'un élément Response en définissant l'en-tête approprié.

  const options = {
    headers: {
      'Content-Type': 'application/json'
    }
  }
  const jsonResponse = new Response('{}', options);

Si vous avez récupéré un Response et que vous souhaitez accéder à son corps, il existe plusieurs méthodes d'assistance que vous pouvez utiliser. Chacune d'elles renvoie un Promise qui résout avec une valeur d'un type différent.

Méthode Description
arrayBuffer Renvoie un ArrayBuffer contenant le corps, sérialisé à octets.
blob Renvoie un objet Blob. Si Response a été créé avec un Blob, ce nouveau Blob aura le même de mots clés. Sinon, le Content-Type de Response est utilisé.
text Interprète les octets du corps en tant que chaîne encodée au format UTF-8.
json Interprète les octets du corps comme une chaîne encodée en UTF-8, puis essaie pour l'analyser au format JSON. Renvoie l'objet obtenu ou génère une TypeError si la chaîne ne peut pas être analysée au format JSON.
formData Interprète les octets du corps de texte sous forme HTML, encodé sous forme de code multipart/form-data ou application/x-www-form-urlencoded Renvoie une FormData ou génère une erreur TypeError si les données ne peuvent pas être analysées.
body Renvoie un ReadableStream pour les données corporelles.

Exemple :

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]

Récupérer depuis un cache

Pour rechercher un élément dans un cache, vous pouvez utiliser la méthode match.

const response = await cache.match(request);
console.log(request, response);

Si request est une chaîne, le navigateur le convertit en Request en appelant new Request(request) La fonction renvoie un Promise qui résout Response si une entrée correspondante est trouvée, ou undefined dans le cas contraire.

Pour déterminer si deux Requests correspondent, le navigateur ne se limite pas à l'URL. Deux sont considérées comme différentes si elles ont des chaînes de requête différentes, En-têtes Vary ou méthodes HTTP (GET, POST, PUT, etc.).

Vous pouvez ignorer tout ou partie de ces éléments en transmettant un objet options en tant que deuxième paramètre.

const options = {
  ignoreSearch: true,
  ignoreMethod: true,
  ignoreVary: true
};

const response = await cache.match(request, options);
// do something with the response

Si plusieurs requêtes mises en cache correspondent, celle qui a été créée en premier est renvoyé. Si vous souhaitez récupérer toutes les réponses correspondantes, vous pouvez utiliser 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.`);

Comme raccourci, vous pouvez effectuer une recherche dans tous les caches à la fois en utilisant caches.match() au lieu d'appeler cache.match() pour chaque cache.

Recherche en cours

L'API Cache ne permet pas de rechercher des requêtes ou des réponses à l'exception des entrées correspondantes avec un objet Response. Cependant, vous pouvez implémenter votre propre recherche en filtrant ou en créant un index.

Filtrage

Une façon d'implémenter votre propre recherche consiste à itérer sur toutes les entrées et et filtrez les données pour n'afficher que ceux qui vous intéressent. Disons que vous voulez trouver toutes articles dont l'URL se termine par .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 cette façon, vous pouvez utiliser n'importe quelle propriété des objets Request et Response pour : filtrer les entrées. Notez que cela peut prendre du temps si vous effectuez une recherche sur de grands ensembles données.

Créer un index

L'autre façon d'implémenter votre propre recherche consiste à gérer un index distinct de les entrées pouvant faire l'objet d'une recherche et stocker l'index dans IndexedDB. Puisqu’il s’agit du genre de pour laquelle IndexedDB a été conçu offre de bien meilleures performances, un grand nombre d'entrées.

Si vous stockez l'URL de Request avec les propriétés incluses dans l'index de recherche vous pouvez facilement récupérer l’entrée de cache correcte après avoir effectué la recherche.

Supprimer un élément

Pour supprimer un élément d'un cache:

cache.delete(request);

Où la requête peut être une chaîne Request ou une chaîne d'URL. Cette méthode utilise également le même objet d'options que cache.match, ce qui vous permet de supprimer plusieurs Request/Response pour la même URL.

cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});

Supprimer un cache

Pour supprimer un cache, appelez caches.delete(name). Cette fonction renvoie une Promise qui résout true si le cache existait et a été supprimé ; ou false dans le cas contraire.

Merci

Grâce à Mat Scales, qui a rédigé la version originale de cet article, est apparu pour la première fois sur WebFundamentals.