Service worker sends two requests

只愿长相守 提交于 2020-01-03 17:26:46

问题


I've implemented a service worker which caches all requests for offline usage, this works fine. But everytime I load a page there are two requests hitting my webserver (one from the service worker and one from the browser)!

How can I cache the request and only load the page once?

service-worker.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);
  });
}

回答1:


So here's what happens whenever you make a request:

  1. The webpage sends a fetch request to the server,
  2. the Service Worker intercepts the request on the 'fetch' event,
  3. pushToCache() fires a fetch request to the server in order to cache the response,
  4. then you respond to the event with a fetch request to the server which will return a Promise for a Response from the web server.

Yup, that makes sense, that thing just sent two requests two the server for every request the page originally made.

One thing you might want to consider is responding from the cache first and then going on the network to get the latest data. This way you will avoid delays in loading in the case of connection issues and it will speed up the loading time of the page even when the user is online.

Let's consider the following scenario: Either the user or the server are offline. Once you fire the request, it will have to time out before it goes to the catch part of the promise and get the cached response.

What you could do once you intercept the event is check the caches for a match and if you find anything, respond to the event with that. Then start a fetch request in order to update the cache. Now if you don't find anything, fire a fetch request, clone the response (because the response body can only be used once), respond with the original response and then update the cache with the cloned response.

What did we achieve with that?

The user gets an instant response, no matter if he's online, offline or on Lie-Fi!

The server gets at most one request and the caches will always get updated with the latest data from the server!

serviceworke.rs is a great resource that can help you understand how to do many interesting things with Service Workers.

This page in particular explains in a bit more detail how what I said above works.



来源:https://stackoverflow.com/questions/51242899/service-worker-sends-two-requests

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!