Service Worker控制器更改从未触发。

6
我希望能在每次页面加载时向服务工作者发送信息。
页面第一次加载时,它会调用register()方法,然后在navigator.serviceWorker上监听"controllerchange"事件,但该事件从未触发。
我该如何知道何时可以开始postMessaging到服务工作者?
navigator.serviceWorker.register(swURL).then(function(){
    var sw;

    if (navigator.serviceWorker.controller) {
        sw = navigator.serviceWorker.controller;
        sw.postMessage('ping');
        return;
    }

    function onchange(){
        sw = navigator.serviceWorker.controller;
        sw.postMessage('ping');
        navigator.serviceWorker.removeEventListener('controllerchange', onchange);
    }

    navigator.serviceWorker.addEventListener('controllerchange', onchange);
}).catch(function(err) {
    // registration failed :(
    console.log('ServiceWorker registration failed: ', err);
});
2个回答

4

我如何知道何时可以开始使用postMessage与服务工作者通信?

只关注这个问题:我建议采用以下方法,利用navigator.serviceWorker.ready承诺:

// navigator.serviceWorker.ready can be used from anywhere in your
// page's JavaScript, at any time.
// It will wait until there's an active service worker, 
// and then resolve with the service worker registration
navigator.serviceWorker.ready.then(registration => {
  registration.active.postMessage('ping');
});

如果你想找出为什么你的controllerchange事件监听器没有触发,我的猜测是你在服务工作者的activate事件中没有使用clients.claim(),这意味着新激活的服务工作者将无法控制当前页面。

对我来说,navigator.serviceWorker.oncontrollerchangenavigator.serviceWorker.ready直到我清除了存储、关闭了选项卡并重新打开它们之前都没有触发。仅仅重新加载页面是没有帮助的。我遵循了这个人的建议:https://dev59.com/Q10a5IYBdhLWcg3w2717#v7GhEYcBWogLw_1b3GCU - GProst
我注意到有趣的一件事。如果在navigator.serviceWorker.ready解析时立即发出请求,SW将无法捕获这些请求,但是如果使用navigator.serviceWorker.oncontrollerchange来进行,则可以捕获它们。通过在body中附加脚本标签进行检查。 - GProst
我正在使用 clients.claim 但仍然无法工作,我已经尝试了你的方法,但仍然没有任何进展。有趣的是,它昨天还能正常工作... - Matteo

3
它没有触发的原因是因为您在Service Worker已经安装/激活之后注册了"controllerchange"事件。 因此,此事件将对新的Service Workers触发,例如使用"skipWaiting()"的Service Workers。但不适用于初始Service Worker。
请使用"navigator.serviceWorker.ready"承诺,该承诺会在检测到活动Service Worker时立即解决,无论何时安装/激活。

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