web-dev-qa-db-ja.com

サービスワーカーはクライアントと通信します

Service Workerからクライアントにメッセージを送信しようとしていますが、

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を使用する必要がありますか?

10
Boris Barroso

clients.fetchAll()が存在するとは思わない。おそらくclients.matchAll()を意味します。これにより、説明する動作が得られるはずです。

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

メッセージを1つずつ送信する必要をなくしながら、Service Workerがクライアントと通信できるようにするためのより良い代替手段は、 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);
});
24
Jeff Posnick

includeUncontrolledオプションを追加すると次のようになります。

for (const client of await clients.matchAll({includeUncontrolled: true, type: 'window'})) {
  client.postMessage(message);
}
0
Tim