kitak blog

Kみたいなエンジニアになりたいブログ

BroadcastChannel API を使ってみた

BroadcastChannel API を使ってみた。

同一オリジンのタブ・ウィンドウ・フレーム間でデータを送受信できる APIAPI の詳しい説明は BroadcastChannel API: A Message Bus for the Web  |  Web  |  Google Developers に譲ります。コードは、パッと見、Cross-Document Messaging とほぼ同じですね。
サポートしているブラウザは、Blink 系のブラウザ( Chrome, Opera )と Firefox のみ( http://caniuse.com/#feat=broadcastchannel ) なのでまだ実戦では使っていないのですが、先日、個人的に便利に使える場面がありました。

先日、プレゼンをする機会があったんですが、プレゼンに使ったツールが https://github.com/ahomu/Talkie というブラウザで動くツールで(このツール、Markdown で書けて、デフォルトでけっこう良い感じに出力してくれるのでオススメです)、そのとき、諸々の事情で手元のPCの画面のブラウザウィンドウで表示しているスライドの内容を、スクリーンで映している別のブラウザウィンドウのスライドに共有・同期する必要がありました。始めは WebSocket を使おうかな、と思っていたのですが、「いや、そういえば BroadcastChannel API ってのがあったよな。まさしくこういうときに使えるのでは」と思い、試しました。

手元で開いているスライドでは、以下のスクリプトを実行して、Talkie でスライドを切り替わったときに現在のページ番号をメッセージとして送ります。

var channel = new BroadcastChannel('talkie');

talkie.changed.subscribe(function(current) {
  channel.postMessage(current.getAttribute('data-page'));
});

スクリーンで映しているスライドでは、以下のスクリプトを実行して、メッセージを受け取り、表示するスライドを同期させます。

window.onmessage = function (e) {
  // 実戦で使う場合は、どの Origin から送られたデータか等チェックしなければいけない
  talkie.jump$.next(e.data);
};

こんなかんじでやりたいことが簡単に実現できました。

実戦では、以下のような仕様を実現するために使えそうです。

  • 動画や音声を再生するサービスで、再生中に別のウィンドウで開いて再生を開始したら、自動で停止する (YouTubeSoundCloud がやっている)
  • 商品にお気に入りをつけることができるサービスで、お気に入りをつけた際に他のウィンドウ・タブに最新の状態を送信する。あるいは、最新の状態に更新するよう促す

こういった仕様を BroadcastChannel API を使わず実現するには、WebSocket を使う、あるいはブラウザだけで完結させるには、LocalStorage や cookie のようなストレージを使って、あらかじめストレージの内容を監視させ、通知を行う際にストレージにデータを書き込むといった実装を行う必要があります。自分も過去にやったことがありますが、実装が面倒な上に監視を setInterval/setTimeout によるポーリングで実現するので、パフォーマンス上の懸念もあります。 BroadcastChannel API でこういった仕様が簡単に実装できるようになるのは、ありがたいですね。