JavaScript/BroadcastChannel

BroadcastChannelオブジェクト

はじめに

BroadcastChannelオブジェクトは、同一オリジン内の複数のブラウジングコンテキスト(ウィンドウ、タブ、フレーム、iframeなど)間でメッセージをブロードキャストするための仕組みを提供します。これにより、同じWebアプリケーションの異なるインスタンス間でシームレスな通信が可能になります。

基本的な使用方法

BroadcastChannelは、特定の名前を持つチャネルを作成し、そのチャネルを通じてメッセージを送受信します。同じ名前のチャネルに接続している全てのコンテキストがメッセージを受信できます。

以下は基本的な使用例です:

// チャネルを作成する
const channel = new BroadcastChannel('app_channel');

// メッセージを送信する
channel.postMessage({ type: 'notification', content: 'データが更新されました' });

// メッセージを受信する
channel.onmessage = (event) => {
  console.log('受信したメッセージ:', event.data);
};

// チャネルを閉じる(使用終了時)
channel.close();

イベントハンドリング

BroadcastChannelは以下のイベントを処理します:

イベント名 説明
message メッセージを受信した時に発火します
messageerror 受信したメッセージをデシリアライズできなかった時に発火します
// messageイベントリスナーを追加
channel.addEventListener('message', (event) => {
  console.log('メッセージ受信:', event.data);
});

// messageerrorイベントリスナーを追加
channel.addEventListener('messageerror', (event) => {
  console.error('メッセージエラー:', event);
});

実用的な例:タブ間同期

BroadcastChannelの一般的なユースケースは、複数のタブ間でアプリケーションの状態を同期させることです。以下は、ユーザーのログイン状態を同期する例です:

const authChannel = new BroadcastChannel('auth_status');

// ログイン処理
function login(username, password) {
  // ログイン処理の実装
  // ...
  
  // ログイン成功後、他のタブに通知
  authChannel.postMessage({
    action: 'login',
    user: { username: username, role: 'user' }
  });
}

// ログアウト処理
function logout() {
  // ログアウト処理の実装
  // ...
  
  // ログアウト後、他のタブに通知
  authChannel.postMessage({
    action: 'logout'
  });
}

// メッセージを受信して処理
authChannel.onmessage = (event) => {
  const data = event.data;
  
  if (data.action === 'login') {
    // UI更新: ログイン状態を反映
    updateUIForLoggedInUser(data.user);
  } else if (data.action === 'logout') {
    // UI更新: ログアウト状態を反映
    updateUIForLoggedOutUser();
  }
};

送信可能なデータ型

BroadcastChannelで送信できるデータ型は、構造化クローンアルゴリズムによってシリアライズ可能なものに限られます。

データ型 送信可能 備考
プリミティブ型(数値、文字列、真偽値など)
オブジェクト、配列 循環参照を含まないもの
Map, Set
Date
Blob, File, FileList
ArrayBuffer, TypedArray
関数 × シリアライズ不可
DOM要素 × シリアライズ不可
Error 一部のプロパティのみ

複数チャネルの管理

大規模なアプリケーションでは、複数のBroadcastChannelを使い分けることで、メッセージの種類ごとに異なるチャネルを設定できます:

// アプリケーションの異なる機能に対応する複数のチャネル
const stateChannel = new BroadcastChannel('app_state');
const notificationChannel = new BroadcastChannel('notifications');
const themeChannel = new BroadcastChannel('theme_settings');

// テーマ変更を他のタブに通知
function changeTheme(themeName) {
  document.body.className = themeName;
  
  // 他のタブにテーマ変更を通知
  themeChannel.postMessage({ theme: themeName });
}

// テーマの同期を受信
themeChannel.onmessage = (event) => {
  document.body.className = event.data.theme;
};

// アプリケーションの終了時にはすべてのチャネルを閉じる
function cleanup() {
  stateChannel.close();
  notificationChannel.close();
  themeChannel.close();
}

// ウィンドウが閉じる際にクリーンアップ
window.addEventListener('beforeunload', cleanup);

ブラウザの互換性と制限事項

BroadcastChannelは現代的なブラウザでサポートされていますが、IE (Internet Explorer)ではサポートされていません。また以下の制限事項があります:

  1. 同一オリジン内のみで機能します(セキュリティのため)
  2. サードパーティCookieの制限により、iframe間の通信に影響する場合があります
  3. シリアライズ不可能なデータは送信できません

ブラウザ間の互換性を確保するには、以下のようにfeature検出を行うとよいでしょう:

if ('BroadcastChannel' in window) {
  // BroadcastChannelが利用可能
  const channel = new BroadcastChannel('app_channel');
  // ...
} else {
  // 代替手段(例:localStorage + storageイベント)を使用
  console.warn('BroadcastChannelはサポートされていません。代替手段を使用します。');
  // ...
}

まとめ

BroadcastChannelオブジェクトは、単一のWebアプリケーションの複数インスタンス間でのリアルタイム通信を簡単に実現する強力なAPIです。タブ間の状態同期、通知の共有、設定の反映などのユースケースに最適です。シンプルなAPIと効率的な通信メカニズムにより、複雑なマルチタブアプリケーションの開発が容易になります。

カテゴリ:JavaScript
カテゴリ:JavaScript