Channel Messaging の使用

Channel Messaging API(チャンネルメッセージング API)を使用すると、同じドキュメントに添付された異なる閲覧コンテキストで実行される2つの別々のスクリプト(2つの IFrame、メインドキュメントと IFrame、SharedWorker を介した2つのドキュメントなど)で直接通信し、両端にポートを持つ双方向チャンネル(またはパイプ)を介して相互にメッセージをやり取りできます。

この記事では、このテクノロジーを使用するための基本を探ります。

註: この機能は Web Workers 内で利用可能です。

ユースケース

チャンネルメッセージングは​​、ゲーム、アドレス帳、または音楽を個人用に選択したオーディオプレーヤーなど、IFrame を介して他のサイトの機能をメインインターフェイスに埋め込むソーシャルサイトがある場合に主に役立ちます。 これらが独立したユニットとして機能する場合は問題ありませんが、メインサイトと IFrame、または異なる IFrame との間のやり取りが必要な場合は困難になります。 例えば、メインサイトからアドレス帳に連絡先を追加したり、メインプロファイルにゲームのハイスコアを追加したり、オーディオプレーヤーからゲームに新しい BGM の選択肢を追加したりする場合はどうすればよいのでしょうか。 ウェブが使用するセキュリティモデルのため、このようなことは従来のウェブテクノロジーを使用したのでは、それほど簡単ではありません。 オリジンがお互いを信頼しているかどうか、そしてメッセージをどのように渡すのかについて考えなければなりません。

一方、メッセージチャンネルは、異なる閲覧コンテキスト間でデータを受け渡すことを可能にする安全なチャンネルを提供することができます。

: 詳細情報とアイデアについては、仕様のウェブ上のオブジェクト機能モデルの基礎としてのポート(英語)のセクションが役に立つでしょう。

簡単な例

はじめに、Github でいくつかのデモを公開しました。 最初に、ページと埋め込まれた <iframe> の間の非常に単純な単一メッセージ転送を示す、チャンネルメッセージングの基本的なデモをチェックしてください(それをライブでも実行してください)。

次に、メインページと IFrame の間で複数のメッセージを送信できる、もう少し複雑な設定を示す、マルチメッセージデモを見てください(これをライブで実行)。

ここでは、マルチメッセージデモに焦点を当てます。 それは次のような感じです。

チャンネルを作成する

デモのメインページには、<iframe> に送信するメッセージを入力するためのテキスト入力を含む単純なフォームがあります。 また、<iframe> から返される確認メッセージを表示するために後で使用する段落もあります。

var input = document.getElementById('message-input');
var output = document.getElementById('message-output');
var button = document.querySelector('button');
var iframe = document.querySelector('iframe');

var channel = new MessageChannel();
var port1 = channel.port1;

// Wait for the iframe to load
// iframe が読み込まれるのを待ちます
iframe.addEventListener("load", onLoad);

function onLoad() {
  // Listen for button clicks
  // ボタンのクリックをリッスンする
  button.addEventListener('click', onClick);

  // Listen for messages on port1
  // port1 でメッセージをリッスンする
  port1.onmessage = onMessage;

  // Transfer port2 to the iframe
  // port2 を iframe に移管する
  iframe.contentWindow.postMessage('init', '*', [channel.port2]);
}

// Post a message on port1 when the button is clicked
// ボタンがクリックされたときに port1 にメッセージを投稿する
function onClick(e) {
  e.preventDefault();
  port1.postMessage(input.value);
}

// Handle messages received on port1
// port1 で受信したメッセージを処理する
function onMessage(e) {
  output.innerHTML = e.data;
  input.value = '';
}

まず MessageChannel() コンストラクタを使用して新しいメッセージチャンネルを作成します。

IFrame が読み込まれたら、ボタン用の onclick ハンドラと MessageChannel.port1 用の onmessage ハンドラを登録します。 最後に、window.postMessage メソッドを使って MessageChannel.port2 を IFrame に移管します。

iframe.contentWindow.postMessage 行の機能をもう少し詳しく調べてみましょう。 これは次の3つの引数を取ります。

  1. 送信するメッセージ。 この初期ポート移管では、このメッセージは空の文字列になる可能性がありますが、この例では 'init' に設定しています。
  2. メッセージの送信先のオリジン。 * は「任意のオリジン」を意味します。
  3. 所有権を受信側の閲覧コンテキストに移管するオブジェクト。 この場合、MessageChannel.port2 を IFrame に移管しているので、メインページとの通信に使用できます。

ボタンをクリックすると、フォームを通常のように送信せず、テキスト入力に入力された値は MessageChannel を介して IFrame に送信します。

IFrame でポートとメッセージを受信する

IFrame では、次の JavaScript があります。

var list = document.querySelector('ul');
var port2;

// Listen for the intial port transfer message
// 初期ポート移管メッセージをリッスンする
window.addEventListener('message', initPort);

// Setup the transfered port
// 移管されたポートを設定する
function initPort(e) {
  port2 = e.ports[0];
  port2.onmessage = onMessage;
}

// Handle messages received on port2
// port2 で受信したメッセージを処理する
function onMessage(e) {
  var listItem = document.createElement('li');
  listItem.textContent = e.data;
  list.appendChild(listItem);
  port2.postMessage('Message received by IFrame: "' + e.data + '"');
}

初期メッセージを window.postMessage メソッドを介してメインページから受信すると、initPort 関数が実行されます。 これは移管されたポートを保存し、メッセージが MessageChannel を通過するたびに呼び出される onmessage ハンドラを登録します。

メインページからメッセージを受信したら、リスト項目を作成し、それを順序なしリストに挿入し、リスト項目の textContent をイベントの data 属性と同じ値に設定します(これは実際のメッセージを含みます)。

次に、最初に IFrame に移管された MessageChannel.port2MessagePort.postMessage を呼び出して、確認メッセージをメッセージチャンネル経由でメインページに投稿します。

メインページで確認を受信する

メインページに戻って、onmessage ハンドラ関数を見ましょう。

// Handle messages received on port1
// port1 で受信したメッセージを処理する
function onMessage(e) {
  output.innerHTML = e.data;
  input.value = '';
}

元のメッセージが正常に受信されたことを確認するメッセージが IFrame から返されると、これは単に確認を段落に出力し、テキスト入力を空にして次のメッセージの送信の準備をします。

仕様

仕様 状態 コメント
HTML Living Standard
Channel messaging の定義
現行の標準

ブラウザーの互換性

MessageChannel

Update compatibility data on GitHub
デスクトップモバイル
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung Internet
MessageChannelChrome 完全対応 4Edge 完全対応 12Firefox 完全対応 41IE 完全対応 10Opera 完全対応 10.6Safari 完全対応 5WebView Android 完全対応 4.4Chrome Android 完全対応 18Firefox Android 完全対応 41Opera Android 完全対応 11Safari iOS 完全対応 5.1Samsung Internet Android 完全対応 1.0

凡例

完全対応  
完全対応

MessagePort

Update compatibility data on GitHub
デスクトップモバイル
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung Internet
MessagePortChrome 完全対応 4Edge 完全対応 12Firefox 完全対応 ありIE 完全対応 10Opera 完全対応 10.6Safari 完全対応 5WebView Android 完全対応 ありChrome Android 完全対応 18Firefox Android 完全対応 ありOpera Android 完全対応 11Safari iOS 完全対応 5.1Samsung Internet Android 完全対応 1.0

凡例

完全対応  
完全対応

関連情報