javascript 仅在离线时使用 ServiceWorker 缓存

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33045517/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 16:04:08  来源:igfitidea点击:

Use ServiceWorker cache only when offline

javascriptbrowser-cacheweb-workerservice-worker

提问by Ruben Martinez Jr.

I'm trying to integrate service workers into my app, but I've found the service worker tries to retrieve cached content even when online, but I want it to prefer the network in these situations. How can I do this? Below is the code I have now, but I don't believe it is working. SW Install code is omitted for brevity.

我正在尝试将 Service Worker 集成到我的应用程序中,但我发现 Service Worker 即使在线时也会尝试检索缓存的内容,但我希望它在这些情况下更喜欢网络。我怎样才能做到这一点?下面是我现在拥有的代码,但我认为它不起作用。为简洁起见,省略了软件安装代码。

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

This seems to lead to warnings like The FetchEvent for "[url]" resulted in a network error response: an object that was not a Response was passed to respondWith().I'm new to service workers, so apologies for any mistaken terminology or bad practices, would welcome any tips. Thank you!

这似乎会导致警告,就像The FetchEvent for "[url]" resulted in a network error response: an object that was not a Response was passed to respondWith().我是服务人员的新手一样,因此对任何错误的术语或不良做法表示歉意,欢迎提供任何提示。谢谢!

采纳答案by Brendan Ritchie

Without testing this out, my guess is that you're not resolving respondWith()correctly in the case where there is no cache match. According to MDN, the code passed to respondWith()is supposed to "resolve by returning a Response or network error to Fetch." So why not try just doing this:

如果没有对此进行测试,我的猜测是respondWith()在没有缓存匹配的情况下您没有正确解析。根据 MDN,传递给的代码respondWith()应该“通过向 Fetch 返回响应或网络错误来解决”。那么为什么不尝试这样做:

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

回答by Marina ES

Why don't you open the cache for your fetch event? I think the process of a service worker is :

为什么不为 fetch 事件打开缓存?我认为 service worker 的过程是:

  • Open your cache

  • Check if the request match with an answer in your cache

  • Then you answer

  • 打开你的缓存

  • 检查请求是否与缓存中的答案匹配

  • 那你回答

OR (if the answer is not in the cache) :

或(如果答案不在缓存中):

  • Check the request via the network

  • Clone your answer from the network

  • Put the request and the clone of the answer in your cache for future use

  • 通过网络检查请求

  • 从网络克隆你的答案

  • 将请求和答案的克隆放入缓存中以备将来使用

I would write :

我会写:

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

回答by Kalle

event.respondWith() expects a promise that resolves to Response. So in case of a cache miss, you still need to return a Response, but above, you are returning nothing. I'd also try to use the cache first, then fetch, but in any case, as the last resort, you can always create a synthetic Response, for example something like this:

event.respondWith() 期望解析为 Response 的承诺。因此,在缓存未命中的情况下,您仍然需要返回 Response,但在上面,您什么都不返回。我也会尝试先使用缓存,然后再获取,但无论如何,作为最后的手段,您始终可以创建一个合成响应,例如这样的:

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