Skip to content
Advertisement

How to update the cached files in my service worker every 30 minutes?

I have this service worker:

//IMPORT POLYFILL
importScripts('cache-polyfill.js');

//INSTALL
self.addEventListener('install', function(e) {
    e.waitUntil(
        caches.open('stock_item_balance_v1').then(function(cache) {
            return cache.addAll([
                '/app/offline_content/purchase/stock_items/stock_items_balance.php',
                '/app/offline_content/purchase/stock_items/js/stock_items_balance.js'
            ]);
        })
    );
});

//FETCH (FETCH IS WHEN YOU CHECK FOR INTERNET)
self.addEventListener('fetch', function(event) {
    //console.log(event.request.url); 

    event.respondWith(
        caches.match(event.request).then(function(response) {
            return response || fetch(event.request);
            
        })
    );
});

In “stock_items_balance.php” i fetch data from my DB. So in every 30 minutes i would like to update my cached pages and reload the window.

So first i have a script that checks for internet connection.
If true, i want to clean/update the cache and reload the page.

How can i do that?

//INTERVAL
setInterval(function(){
    
  //CLEAN/UPDATE CACHED FILES
  serviceworker.update(); // ???

  //RELOAD PAGE
  window.location.reload();

}, 180000); 

Advertisement

Answer

(I think you have a larger question as to whether the approach you describe is actually going to give a good, predictable, offline-capable experience for your users, but I’m just going to focus on the actual technical question you asked.)

Messaging the service worker

First off, you should keep in mind that it’s possible to have multiple tabs open for the same URL, and if you, you’re going to end up with your update code potentially running multiple times. The code in this answer handles the “reload” step for you from inside of the service worker, after the asynchronous cache update has completed, by getting a list of all the active clients of the service worker and telling each to navigate to the current URL (which is effectively a reload).

// Additions to your service worker code:
self.addEventListener('message', (event) => {
  // Optional: if you need to potentially send different
  // messages, use a different identifier for each.
  if (event.data === 'update') {
    event.waitUntil((async () => {
      // TODO: Move these URLs and cache names into constants.
      const cache = await caches.open('stock_item_balance_v1');
      await cache.addAll([
        '/app/offline_content/purchase/stock_items/stock_items_balance.php',
        '/app/offline_content/purchase/stock_items/js/stock_items_balance.js'
      ]);
      const windowClients = await clients.matchAll();
      for (const windowClient of windowClients) {
        // Optional: check windowClient.url first and
        // only call navigate() if it's the URL for one
        // specific page.
        windowClient.navigate(windowClient.url);
      }
    })());
  }
});
// Additions to your window/page code:
setInterval(() => {
  if (navigator.serviceWorker.controller) {
    navigator.serviceWorker.controller.postMessage('update');
  }
}, 180000); 

What won’t work

The Cache Storage API is available from both inside a service worker and inside of your page’s window scope. Normally what I’d recommend that folks do is to open up the same cache from the window context, and call cache.add() to update the cached entry with the latest from the network. However, calling cache.add() from the window context will cause the network request to be intercepted by your fetch handler, and at that point, your response won’t actually come from the network. By calling cache.add() from inside your service worker, you can guarantee that the resulting network request won’t trigger your fetch handler.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement