问题:

我一直在尝试从服务人员向客户发送消息,但是如果我使用

self.clients.matchAll()
.then((clients) => {
  clients.forEach(function(client) {
    client.postMessage({msg: 'Hello from SW'})
  })
})

即使我在浏览器中打开了一个选项卡,它也不会发送到任何客户端,但是如果我从客户端服务工作者发送消息

// client
navigator.serviceWorker.controller.postMessage({title: 'Send message from client'})

并在服务人员中

self.addEventListener('message', function(event) {
  self.clients.fetchAll()
    .then((clients) => {
      clients.forEach(function(client) {
        client.postMessage({msg: 'Hello from SW'})
     })
  })
})

它可以发送消息并寻找客户。我做错了什么?我应该使用indexedDB吗?

回答:

我不相信那clients.fetchAll()存在。您可能的意思是clients.matchAll(),这应该给您您所描述的行为:

self.clients.matchAll().then(clients => {
    clients.forEach(client => client.postMessage({msg: 'Hello from SW'}));
})

一个更好的替代方案是使用 Broadcast Channel API ,它允许服务工作线程与客户端通信,同时避免必须逐一发送消息。现在最新版本的 Chrome 和 Firefox 都支持它。

// From service-worker.js:
const channel = new BroadcastChannel('sw-messages');
channel.postMessage({title: 'Hello from SW'});

// From your client pages:
const channel = new BroadcastChannel('sw-messages');
channel.addEventListener('message', event => {
    console.log('Received', event.data);
});

Service worker 如何与客户端通信
标签: