在JavaScript中强制跳过Service Worker进行重新加载

12

Service Workers 可以通过设计与刷新按钮发生干扰。 在桌面版 Chrome 上,您可以按住 Shift 键并单击刷新按钮以执行强制重新加载,忽略任何已安装的 ServiceWorker。

是否有一种方式可以通过 JavaScript 强制重新加载并忽略 SW?

(我需要这样做是因为我想给移动用户一个按钮,以便在 SW 开始表现不良时使用。手机没有 Shift 键。)


2
{btsdaf} - Dan Fabulich
如果你想删除所有缓存,可以使用caches.delete https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Deleting_old_caches 你可以通过你的js代码(按钮点击处理程序)与service worker进行通信,然后service worker消息处理程序可以删除缓存(或只删除一些)。当service worker完成后,重新加载页面:http://craig-russell.co.uk/2016/01/29/service-worker-messaging.html#.We2hlHWCzHQ - HMR
2个回答

16

如果在刷新之前 注销 Service Worker,下一次页面加载将会在没有 Service Worker 的情况下进行加载。

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

我应该在哪里使用这段代码?在窗口的“beforeunload”事件处理程序中吗?每次重新加载时注销SW的影响是什么? - Arik
@Arik 我从未打算在每次重新加载时运行此代码。我打算为用户提供一个屏幕上的“强制重新加载”按钮;代码将出现在按钮的单击处理程序中。我认为在每次重新加载时强制刷新没有意义;此时,我认为您真正想要的是完全卸载服务工作者而不进行替换。(或者,如果您只想在刷新时激活更新的服务工作者,那就是一个完全不同的问题。) - Dan Fabulich
丹,我正在解决另一个问题(在硬刷新后无法使我的软件响应获取事件),我错误地将你的答案与我的问题联系起来 :) - Arik

1

我来举个例子,这是我发表评论的内容:

页面脚本:

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

服务工作者:
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)
              ,[]
            )
          )
      );
    }
  }
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接