最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Force reload skipping Service Worker in JavaScript - Stack Overflow

programmeradmin1浏览0评论

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.)

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.)

Share Improve this question asked Oct 23, 2017 at 4:19 Dan FabulichDan Fabulich 39.6k42 gold badges145 silver badges184 bronze badges 2
  • 2 I'll tell you one thing I tried that doesn't do what I want. window.location.reload(true) (the forcedRefresh parameter), is generally supposed to be equivalent to shift-refresh, but in my tests, location.reload(true) doesn't override/ignore the SW; as far as SWs are concerned, it's the same as location.reload(false). (Is that a bug in Chrome??) – Dan Fabulich Commented Oct 23, 2017 at 4:20
  • If you want to delete all caches you could use caches.delete developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/… You could communicate with the service working from your js code (button click handler) and the service worker message handler could delete the caches (or only some). When the service worker is done then reload the page: craig-russell.co.uk/2016/01/29/… – HMR Commented Oct 23, 2017 at 8:13
Add a comment  | 

2 Answers 2

Reset to default 17

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);
  }
});

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)
              ,[]
            )
          )
      );
    }
  }
);
发布评论

评论列表(0)

  1. 暂无评论