6

我已经实现了一个服务工作者,它缓存所有离线使用的请求,这工作正常。但是每次我加载一个页面时,都会有两个请求访问我的网络服务器(一个来自服务工作者,一个来自浏览器)!

如何缓存请求并且只加载一次页面?

服务工作者.js

self.addEventListener('install', function(event) {
  //load error page which will show if user has no internet
  var errorPage = new Request('/?p=error&offline');
  event.waitUntil(pushToCache(errorPage));
});

//If any fetch fails, it will look for the request in the cache and serve it from there first
self.addEventListener('fetch', function(event) {
  event.waitUntil(pushToCache(event.request));

  event.respondWith(
    fetch(event.request) //try loading from internet
    .catch(function (error) {
      return fetchFromCache(event.request);
    }) //no internet connection try getting it from cache
  );
});

function pushToCache(request){
  if(request.method == "GET"){
    return caches.open('stm-app').then(function (cache) {
      return fetch(request).then(function (response) {
        return cache.put(request, response);
      });
    });
  }
};

function fetchFromCache(request) {
  return caches.open('stm-app').then(function (cache) {
    return cache.match(request).then(function (matching) {
      if(!matching || matching.status == 404){
        return fetchFromCache(new Request('/?p=error&offline')); //show page that user is offline
      }else{
        return matching;
      }
    });
  });
}

sw-register.js

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('service-worker.js')
  .then(function(registration) {
    console.log('Registered:', registration);
  })
  .catch(function(error) {
    console.log('Registration failed: ', error);
  });
}
4

1 回答 1

9

因此,每当您提出请求时,都会发生以下情况:

  1. 网页向服务器发送 fetch 请求,
  2. Service Worker 拦截 'fetch' 事件的请求,
  3. pushToCache() 向服务器发出获取请求以缓存响应,
  4. 然后你向服务器发送一个 fetch 请求来响应事件,这将返回一个来自 web 服务器的响应的 Promise。

是的,这是有道理的,对于页面最初发出的每个请求,那个东西只是向服务器发送了两个请求。

您可能要考虑的一件事是先从缓存中响应,然后再通过网络获取最新数据。这样,您将避免在连接问题的情况下加载延迟,并且即使用户在线,它也会加快页面的加载时间。

让我们考虑以下场景:用户或服务器处于脱机状态。一旦你触发请求,它必须超时才能进入承诺的捕获部分并获得缓存的响应。

拦截事件后,您可以做的是检查缓存是否匹配,如果发现任何内容,请使用该事件响应事件。然后启动获取请求以更新缓存。现在,如果您没有找到任何内容,请触发 fetch 请求,克隆响应(因为响应主体只能使用一次),使用原始响应进行响应,然后使用克隆的响应更新缓存。

我们用它实现了什么?

无论用户是在线、离线还是在 Lie-Fi 上,用户都会得到即时响应!

服务器最多收到一个请求,并且缓存将始终使用来自服务器的最新数据进行更新!

serviceworke.rs是一个很好的资源,可以帮助您了解如何使用 Service Worker 做许多有趣的事情。

这个页面特别详细地解释了我上面所说的工作原理。

于 2018-07-09T10:44:18.010 回答