web-dev-qa-db-ja.com

オフライン時にのみServiceWorkerキャッシュを使用する

Service Workerをアプリに統合しようとしていますが、Service Workerがオンラインでもキャッシュされたコンテンツを取得しようとしていることがわかりましたが、このような状況ではネットワークを優先したいと考えています。これどうやってするの?以下は私が現在持っているコードですが、それが機能しているとは思いません。 SW Installコードは簡潔にするために省略されています。

_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;
        }
      });
    })
  );
});
_

これはThe FetchEvent for "[url]" resulted in a network error response: an object that was not a Response was passed to respondWith().のような警告につながるようです。サービスワーカーは初めてです。そのため、誤った用語や悪習があれば、どんなヒントでも歓迎します。ありがとうございました!

22

これをテストしないと、キャッシュの一致がない場合、respondWith()を正しく解決していないと思います。 MDNによるとrespondWith()に渡されるコードは、「Fetchに応答またはネットワークエラーを返すことによって解決する」ことになっています。だから、これをやってみてはどうですか:

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

フェッチイベントのキャッシュを開いてみませんか?サービスワーカーのプロセスは次のとおりです。

  • キャッシュを開く

  • リクエストがキャッシュ内の回答と一致するかどうかを確認します

  • 次に答えます

OR(答えがキャッシュにない場合):

  • ネットワーク経由でリクエストを確認する

  • ネットワークから回答を複製する

  • 将来の使用のために、リクエストと回答のクローンをキャッシュに入れます

私は書くでしょう:

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);
        })
      })
    }
 );
});
6
Marina ES

event.respondWith()は、Responseに解決されるプロミスを期待します 。そのため、キャッシュミスが発生した場合でも応答を返す必要がありますが、上記では何も返しません。最初にキャッシュを使用してからフェッチすることも試みますが、いずれの場合でも、最後の手段として、次のような合成応答をいつでも作成できます。

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