【问题标题】:communication between service worker instancesService Worker 实例之间的通信
【发布时间】:2018-08-22 01:27:15
【问题描述】:

我正在尝试在安装 Service Worker 和已激活 Service Worker 之间建立通信通道。 我已尝试执行以下操作:

关于正在安装的 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]);

在活跃的 Service Worker 上:

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

这行不通,我什么也得不到... 想法?

【问题讨论】:

    标签: service-worker


    【解决方案1】:

    这就是我最终实现它的方式。

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

     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 可以处于其他状态(冗余、已删除?、其他?),所以可能有两个以上的 ServiceWorker 活着,然后对通道上应答方身份的假设可能是错误的。 ..

    【讨论】:

      【解决方案2】:

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

      您可能需要将页面本身用作在 Service Worker 之间发送/接收消息的代理:

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

      【讨论】:

      • 我想过使用页面作为代理,但是页面不是静态的。它很可能在网站内的页面之间导航,因此我无法拥有稳定的代理频道。
      • 感谢您的链接!我尝试了 Jake 描述的第三个选项 BroadcastChannel,它就像一个魅力。修改你的答案,我会批准它
      • 我建议将您的解决方案添加到答案中,以便搜索此问题的用户可以准确地看到您是如何解决它的。
      猜你喜欢
      • 2016-06-07
      • 1970-01-01
      • 2014-03-18
      • 2014-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多