28

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

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().我是服务人员的新手,因此对任何错误的术语或不良做法表示歉意,欢迎任何提示。谢谢!

4

3 回答 3

17

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

self.addEventListener('fetch', function(event) {
  event.respondWith(
    fetch(event.request).catch(function() {
      return caches.match(event.request);
    })
  );
});
于 2015-10-11T22:51:31.423 回答
6

为什么不为 fetch 事件打开缓存?我认为服务人员的流程是:

  • 打开你的缓存

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

  • 然后你回答

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

  • 通过网络检查请求

  • 从网络克隆你的答案

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

我会写:

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);
        })
      })
    }
 );
});
于 2018-03-12T15:37:10.617 回答
5

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

return new Response("Network error happened", {"status" : 408, "headers" : {"Content-Type" : "text/plain"}});
于 2018-08-23T22:43:25.653 回答