web-dev-qa-db-fra.com

Utiliser le cache ServiceWorker uniquement en mode hors connexion

J'essaie d'intégrer les opérateurs de service dans mon application, mais j'ai constaté que celui-ci essayait de récupérer le contenu mis en cache même lorsqu'il était en ligne, mais je souhaite qu'il préfère le réseau dans ces situations. Comment puis-je faire ceci? Vous trouverez ci-dessous le code que j'ai maintenant, mais je ne crois pas qu'il fonctionne. Le code d'installation SW est omis pour des raisons de brièveté.

var CACHE_NAME = 'my-cache-v1';
var urlsToCache = [
  /* my cached file list */
];

self.addEventListener('install', function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

/* request is being made */
self.addEventListener('fetch', function(event) {
  event.respondWith(
    //first try to run the request normally
    fetch(event.request).catch(function() {
      //catch errors by attempting to match in cache
      return caches.match(event.request).then(function(response) {
        // Cache hit - return response
        if (response) {
          return response;
        }
      });
    })
  );
});

Cela semble donner lieu à des avertissements tels que The FetchEvent for "[url]" resulted in a network error response: an object that was not a Response was passed to respondWith(). Je suis nouveau dans le secteur des services, donc des excuses pour la terminologie erronée ou les mauvaises pratiques, apprécierions tous les conseils. Je vous remercie!

16

Sans tester cela, je suppose que vous ne résolvez pas respondWith() correctement dans le cas où il n'y a pas de correspondance de cache. Selon MDN , le code transmis à respondWith() est censé "résoudre en renvoyant une réponse ou une erreur réseau à Fetch". Alors pourquoi ne pas essayer de faire ceci:

self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetch(event.request).catch(function() {
      return caches.match(event.request);
    })
  );
});
7
Brendan Ritchie

Pourquoi n'ouvrez-vous pas le cache pour votre événement fetch? Je pense que le processus d'un agent de service est le suivant:

  • Ouvrez votre cache

  • Vérifiez si la demande correspond à une réponse dans votre cache

  • Alors tu réponds 

OU (si la réponse n'est pas dans le cache):

  • Vérifier la demande via le réseau

  • Clonez votre réponse depuis le réseau

  • Mettez la demande et le clone de la réponse dans votre cache pour une utilisation future

Je souhaiterai écrire :

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.open(CACHE_NAME).then(cache => {
     return cache.match(event.request).then(response => {
      return response || fetch(event.request)
      .then(response => {
        const responseClone = response.clone();
        cache.put(event.request, responseClone);
        })
      })
    }
 );
});
5
Marina ES

event.respondWith () attend une promesse résolue en réponse . Ainsi, en cas d’absence de cache, vous devez toujours renvoyer une réponse, mais vous ne renvoyez rien. J'essayerais également d'utiliser d'abord le cache, puis de chercher, mais dans tous les cas, en dernier recours, vous pouvez toujours créer une réponse synthétique, par exemple quelque chose comme:

return new Response("Network error happened", {"status" : 408, "headers" : {"Content-Type" : "text/plain"}});
2
Kalle