Force reload skipping Service Worker in JavaScript

痴心易碎 提交于 2019-12-23 12:08:39

问题


Service Workers can interfere with the refresh button (by design). On desktop Chrome, you can hold shift and click the refresh button to do a hard reload, ignoring any installed ServiceWorker.

Is there a way to force a reload ignoring the SW in JavaScript?

(I want this so I can give mobile users a button to push if the SW starts misbehaving. Phones don't have a shift key.)


回答1:


If you unregister the Service Worker before refreshing, the next page load will load without the Service Worker.

navigator.serviceWorker.getRegistration().then(function(reg) {
  if (reg) {
    reg.unregister().then(function() { window.location.reload(true); });
  } else {
     window.location.reload(true);
  }
});



回答2:


Here is an example of what I commented on:

page script:

if('serviceWorker' in navigator){
  // Register service worker
  navigator.serviceWorker.register('/service-worker.js')
  .then(
    reg =>
      console.log("SW registration succeeded. Scope is "+reg.scope)
    ,err =>
      console.error("SW registration failed with error "+err)
  );
}

const send_message_to_sw = (msg) =>
  new Promise(
    (resolve, reject) => {
      // Create a Message Channel
      const msg_chan = new MessageChannel();

      // Handler for recieving message reply from service worker
      msg_chan.port1.onmessage = (event) => {
          if(event.data.error){
              reject(event.data.error);
          }else{
              resolve(event.data);
          }
      };

      // Send message to service worker along with port for reply
      navigator.serviceWorker.controller.postMessage(
        msg
        , [msg_chan.port2]
      );
  }
);

document.body.addEventListener(
  "click"
  ,()=>
    send_message_to_sw(
      {
        action:"delete"
        ,cache:/^v1$/
        ,url:/.*bundle.js$/
      }
    )
    .then(
      (msg)=>
        console.log("deleted:",msg)
    )
);

Service worker:

console.log("SW Startup!");

// Install Service Worker
self.addEventListener(
  'install'
  ,(event)=>
    console.log('installed!')
);

// Service Worker Active
self.addEventListener(
  'activate'
  ,(event)=>
  console.log('activated!')
);
self.addEventListener(
  'fetch'
  ,(event) =>
    event.respondWith(
      caches.match(event.request)
      .then((resp) =>
          resp 
          || 
          fetch(event.request)
          .then(
            (response) =>
              caches.open('v1')
              .then(
                (cache) => {
                  cache.put(event.request, response.clone());
                  return response;
                }
              )  
          )
      )
    )
);
self.addEventListener(
  'message'
  ,(event) =>{
    const data = event.data || {};
    if(data.action === "delete"){
      var p = 
        caches.keys()
        .then(
          (keyList) =>
            keyList
            .filter(
              key=>data.cache.test(key)
            )
        )
      ;
      if(data.url === undefined) {
        p = p.then(
          (keyList) =>
            Promise.all(
              keyList
              .map((key) =>{
                caches.delete(key);
                return key;
              }
            )
          )
        )
      }else {
        p = p.then(
          (keyList) =>
            Promise.all(
              keyList
              .map((key) =>
                caches.open(key)
                .then(
                  (cache)=>
                    Promise.all([
                      cache
                      ,cache.keys()
                    ])
                )
                .then(
                  ([cache,items])=>
                    Promise.all(
                      items
                      .filter(item=>data.url.test(item.url))
                      .map(
                        item=>{
                          cache.delete(item);
                          return key + ":" + item.url
                        }
                      )
                    )
                )
            )
          )
        )        
      }
      return p.then(
        (keys)=>
          event.ports[0].postMessage(
            keys
            .reduce(
              (acc,item)=>acc.concat(item)
              ,[]
            )
          )
      );
    }
  }
);


来源:https://stackoverflow.com/questions/46881906/force-reload-skipping-service-worker-in-javascript

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