Service Workers は、メインのJavaScriptスレッドから分離されています。 特別な種類のWebワーカーであるため、同じ制限があります。 どのようにしてメインスレッドに戻って通信しますか? ブラウザは、チャネルメッセージングAPIを提供します。 このAPIを使用すると、2つのスクリプトが、共有チャネルで単純なメッセージを渡すことによって通信できます。

iframeとの通信も便利ですが、この投稿ではワーカーのユースケースに焦点を当てます。

チャネルをインスタンス化する

次の構文を使用して、チャネルをインスタンス化できます。

const channel = new MessageChannel()

タイプMessageChannelchannelオブジェクトでは、port1port2の2つのポートにアクセスできます。

要点は、チャネルの両端で一方のポートでリッスンし、もう一方のポートにメッセージを送信することです。

チャネルを作成するときは、メッセージをport2に送信します。

チャネルを介したメッセージの送信

postMessage()メソッドを使用してチャネルを介してメッセージを送信します。このメソッドは、スクリプトがブラウザーで実行されている場合、windowオブジェクトで使用できます。

const data = { color: 'green' }
const channel = new MessageChannel()
window.postMessage(data, [channel.port2])

受信側で着信メッセージを聞く

受信側では、たとえばService Workerで、selfにリスナーを追加します。これは、ワーカーが自分自身にアクセスする必要があるグローバルです。

self.addEventListener('message', event => {
  console.log('Incoming message')
})

パラメータとして渡されたeventオブジェクトには、dataプロパティでこのイベントに関連付けられたデータが含まれています。

self.addEventListener('message', event => {
  console.log('Incoming message')
  console.log(event.data)
})

メッセージを送り返す

メッセージを送り返すために、イベントリスナーでは、event.ports[0]を参照して他のポートにアクセスできます。

このオブジェクトでは、postMessage()を呼び出して、追加のデータをポストバックできます。

self.addEventListener('message', event => {
  console.log('Incoming message')
  console.log(event.data)

  const data = { shape: 'rectangle' }
  event.ports[0].postMessage(data)
})

送信者としてメッセージを受信する

送信者は、作成したチャネルオブジェクトにアクセスできるため、onmessageハンドラーをmessage.port1オブジェクトにアタッチできます。

channel.port1.onmessage = event => {
  console.log(event.data)
}

どんなメッセージを送ることができますか?

postMessage()では、基本的なJavaScriptデータ型を送信できます。 これは、ブール値、文字列、数値、およびオブジェクトを意味します。 配列を使用して、複数のオブジェクトを渡すことができます。