我试图在安装服务工作者和激活的服务工作者之间建立通信通道。 我试图做以下事情:
安装服务工作者:
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');
});
这不起作用,我什么都没得到...... 想法?
答案 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]