服务工作者实例之间的通信

时间:2018-03-13 17:16:42

标签: service-worker

我试图在安装服务工作者和激活的服务工作者之间建立通信通道。 我试图做以下事情:

安装服务工作者:

 if ((self.registration.active == null) ||
     (self.registration.active.state != "activated")) {
      return;
 }

 var messageChannel = new MessageChannel();
 messageChannel.port1.onmessage = function(event){
      if (event.data.error) {
           console.log("got error from active");
      }

      else {
           console.log("got answer from active");
      }
 };

 self.registration.active.postMessage({message: 'hey', port: messageChannel.port2}, [messageChannel.port2]);

在活动服务工作者上:

 self.addEventListener('message', function(event) {
      console.log('received message');
 });

这不起作用,我什么都没得到...... 想法?

2 个答案:

答案 0 :(得分:1)

以下是我最终实现此目的的方法。

启动时的每个serviceWorker(工作者全局范围内的代码)都连接到广播频道,如下所示:

 var comChannel = new BroadcastChannel('SWCom');
 comChannel.addEventListener('message', event => {
      handleMessageEvent(event);
 });

此渠道仅在服务工作者之间共享。 要将消息发布到其他SW,SW可以只在频道comChannel.postMessage('hey there');上广播,并且将调用任何已注册的侦听器。

我遇到的一个并不是与频道有关的复杂因素是我很难识别每个SW生命周期状态。如果我想在SW之间进行交流,如果我不知道每个人中谁是谁,那么它实际上无法用于任何目的。 SW目前无法获得自己的ServiveWorker对象的引用,标准中存在一个未解决的问题 - https://github.com/w3c/ServiceWorker/issues/1077

在我的用例中,我通过在安装时执行通信(符合我的需要......)绕过了这个限制,如下所示:

 self.addEventListener('install', function(event) {
      if (self.registration.active != null) {
           // if we got here it means this is a new SW that's
           // starting install and there's an active one running.
           // So we can send a message on the broadcast channel,
           // whomever answers should be the active SW.
      }

      // ..
      // installation code
      // ..
 }

有一点需要注意 - 我不确定这是否已得到很好的实施。 我相信SW可以处于其他状态(冗余,删除?,其他?),因此可能有两个以上的ServiceWorkers存活,然后对通道上应答方身份的假设可能是错误的。 ..

答案 1 :(得分:0)

Jake提供了一些很好的消息传递示例,您可以从中获取解决方案。 https://gist.github.com/jakearchibald/a1ca502713f41dfb77172be4523a9a4c

您可能需要将页面本身用作服务工作者之间发送/接收消息的代理:

[SW1] <== message ==> [Page JS] <== message ==> [SW2]