简体   繁体   English

将eventlisteners放在serviceworker上的位置

[英]Where to put eventlisteners for serviceworker

Basicly I'm trying to accomplish to show a dialog when a new serviceworker version has been detected, and then to have user decide to reload to fetch it. 基本上我正在尝试完成以在检测到新的serviceworker版本时显示对话框,然后让用户决定重新加载以获取它。 To accomplish this we need to actively set skipWaiting before we reload window. 为了实现这一点,我们需要在重新加载窗口之前主动设置skipWaiting

Here's my action: 这是我的行动:

  onClickHandler = () => {
    console.log('on click', 'posting skipWaiting');
    navigator.serviceWorker.controller.postMessage('skipWaiting');
  };

Here's my attempt to create the eventListener: 这是我尝试创建eventListener:

navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      registration.onupdatefound = () => {
        const installingWorker = registration.installing;
        if (installingWorker == null) {
          return;
        }
        installingWorker.onstatechange = () => {
          console.log('worker state', installingWorker.state);
          if (installingWorker.state === 'installed') {
            if (navigator.serviceWorker.controller) {
              console.log(
                'New content is available and will be used when all ' +
                  'tabs for this page are closed.'
              );

              navigator.serviceWorker.addEventListener('message', event => {
                console.log('skip waiting');
                if (event.data === 'skipWaiting') {
                  self.skipWaiting();
                }
              });
            }
          }
        };
      };
    })
    .catch(error => {
      console.error('Error during service worker registration:', error);
    });

The issue is that navigator.serviceWorker.addEventListener('message', event => does not get triggered. Am I declaring the listener wrong? 问题是navigator.serviceWorker.addEventListener('message', event =>没有被触发。我是否声明监听器错了?

You are close. 你很亲密 In your installed block you can make a check for 在您安装的区块中,您可以进行检查

navigator.serviceWorker.controller

If this exists it means that the old content will have been purged and the fresh content will have been added to the cache. 如果存在,则表示旧内容已被清除,新内容将被添加到缓存中。 Its a perfect time to display a message or to force a refresh. 它是显示消息或强制刷新的最佳时机。

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

                    $log.debug('The service worker has been registered ', registration);

                    if(navigator.online) {
                        toastr.warning('Offline Mode', 'Application Status');
                    }

                    // updatefound is fired if service-worker.js changes.
                    registration.onupdatefound = function () {
                        // The updatefound event implies that reg.installing is set; see
                        // https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-container-updatefound-event
                        var installingWorker = registration.installing;

                        installingWorker.onstatechange = function () {
                            switch (installingWorker.state) {
                                case 'installed':
                                    if (navigator.serviceWorker.controller) {
                                        // At this point, the old content will have been purged and the fresh content will
                                        // have been added to the cache.
                                        // It's the perfect time to display a "New content is available; please refresh."
                                        // message in the page's interface.
                                        toastr.info('Application has been updated, please refresh this page for the most recent version');

                                        window.location.reload();

                                        });
                                        caches.delete('scope-dynamic').then(function () {
                                            $log.debug('Killed the dynamic cache!');
                                        })
                                        $log.debug('New or updated content is available.');
                                    } else {
                                        // At this point, everything has been precached.
                                        // It's the perfect time to display a "Content is cached for offline use." message.
                                        toastr.success('Content is cached for offline use.', 'Application Status');
                                        $log.debug('Content is now available offline!');
                                    }
                                    break;

                                case 'redundant':
                                    $log.error('The installing service worker became redundant.');
                                    break;

                            }
                        };
                    };
                }).catch(function (e) {
                    $log.error('Error during service worker registration:', e);
                });

There is some angular stuff sprinkled in there but that should help you get to where you wanna be. 那里撒了一些棱角分明的东西,但这应该可以帮助你到达你想去的地方。

The problem here is that the code you provided has only defined receiving & sending messages from your client to the service worker. 这里的问题是您提供的代码仅定义了从客户端向服务工作者接收和发送消息。

The below method has defined a message to be sent to your controller (active) service worker. 以下方法定义了要发送给控制器(活动)服务工作者的消息。

onClickHandler = () => {
    console.log('on click', 'posting skipWaiting');
    navigator.serviceWorker.controller.postMessage('skipWaiting');
};

The definition below has added an event listener on your ServiceWorker container to receive any messages sent from the service worker. 下面的定义在ServiceWorker容器上添加了一个事件侦听器,用于接收从服务工作者发送的任何消息。

navigator.serviceWorker.addEventListener('message', event => {
    console.log('skip waiting');
    if (event.data === 'skipWaiting') {
        self.skipWaiting();
    }
});

You now need to define the event handlers from the service worker file to receive & send messages. 您现在需要从服务工作文件中定义事件处理程序以接收和发送消息。

In the service worker file, to receive messages from the client: 在服务工作器文件中,要从客户端接收消息:

self.addEventListener('message', function handler (event) {
   console.log('skip waiting');
   if (event.data === 'skipWaiting') {
      self.skipWaiting();
   }
});

To send messages from serviceworker to your client: 要从serviceworker向您的客户发送消息:

self.addEventListener('fetch', function(event) {
  self.clients.matchAll().then(all => all.map(client => client.postMessage('data from webworker')));
});

You could also send data back from the serviceworker using a MessageChannel. 您还可以使用MessageChannel从serviceworker发回数据。 On your client you would have to define something like below: 在您的客户端上,您必须定义如下内容:

    navigator.serviceWorker
        .register(swUrl)
        .then(registration => {
            var messageChannel = new MessageChannel();
            // listener for messages from the ServiceWorker    
            messageChannel.port1.addEventListener('message', (event) => console.log(event.data)); 

            function sendMessage (message) {
                //send message to the active service worker
                navigator.serviceWorker.controller.postMessage(message, [messageChannel.port2]);
            }
      onClickHandler = () => {
          sendMessage('skipWaiting');
      };
   });

I found the below article to be quite helpful. 我发现下面的文章非常有帮助。

ServiceWorker, MessageChannel & postMessage by Nicolás Bevacqua NicolásBevacqua提供的ServiceWorker,MessageChannel和postMessage

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM