方法:ServiceWorker检查是否准备好更新

Aiv*_*ras 16 javascript service-worker sw-precache

我想要实现的目标:

  • 用loader/spinner渲染页面

  • 如果service-worker.js已注册并处于活动状态,则检查更新

    • 如果没有更新,则删除加载程序
    • 如果updatefound安装了新版本,则重新加载页面
  • 否则注册 service-worker.js
    • 什么时候updatefound,意味着新的安装,删除装载机

我正在使用sw-precache模块生成service-worker.js并遵循注册码:

window.addEventListener('load', function() {

  // show loader
  addLoader();

  navigator.serviceWorker.register('service-worker.js')
    .then(function(swRegistration) {

      // react to changes in `service-worker.js`
      swRegistration.onupdatefound = function() {
        var installingWorker = swRegistration.installing;
        installingWorker.onstatechange = function() {
          if(installingWorker.state === 'installed' && navigator.serviceWorker.controller){

            // updated content installed
            window.location.reload();
          } else if (installingWorker.state === 'installed'){

            // new sw registered and content cached
            removeLoader();
          }
        };
      }

      if(swRegistration.active){
        // here I know that `service-worker.js` was already installed
        // but not sure it there are changes
        // If there are no changes it is the last thing I can check
        // AFAIK no events are fired afterwards
      }

    })
    .catch(function(e) {
      console.error('Error during service worker registration:', e);
    });
});
Run Code Online (Sandbox Code Playgroud)

阅读规范后很明显,没有像这样的东西的处理程序updatenotfound.看起来像 serviceWorker.register检查是否service-worker.js通过运行get-newest-worker-algorithm在内部进行了更改,但我看不到通过公共API公开的类似方法.

我认为我的选择是:

  • 在服务工作者注册变为活动状态后等待几秒钟以查看是否onupdatefound被触发
  • service-worker.js如果未更新缓存,则从代码触发自定义事件

还有其他建议吗?


编辑:

我想出了一些代码,通过postMessage()在SW注册和SW客户端之间使用来解决这个问题(如@pate建议的那样)

以下演示试图通过postMessageSW客户端和SW注册之间的检查,但由于SW代码已经缓存DEMO而失败


编辑:

所以现在看起来我无法实现我想要的东西,因为:

  1. 当服务工作者处于活动状态时,您无法通过评估SW中的某些代码来检查更新 - 这仍然是相同的缓存SW,没有更改
  2. 你需要等待onupdatefound,没有其他任何可以通知SW的变化
  3. activation 之前的SW来了 onupdatefound
  4. 如果没有变化,之后什么都不会发生 activation
  5. SW注册update()不成熟,不断变化,Starting with Chrome 46, update() returns a promise that resolves with 'undefined' if the operation completed successfully or there was no update
  6. 设置超时以推迟视图渲染是次优的,因为没有明确的答案应该设置多长时间,它还取决于SW大小

Fab*_*cca 0

我脑海中浮现的唯一方法是正常启动加载程序,然后在服务工作线程中的安装函数中将其删除。我会在你的 service-worker.js 中尝试一下:

self.addEventListener('install', function(e) {
  console.log('[ServiceWorker] Install');
  e.waitUntil(
    caches.open(cacheName).then(function(cache) {
      console.log('[ServiceWorker] Caching app shell');
      return cache.addAll(filesToCache);
    }).then(function() {
        ***removeLoader();***
        return self.skipWaiting();
    })
  );
});
Run Code Online (Sandbox Code Playgroud)