[解決済み】タブやウィンドウ間の通信について
質問
ブラウザの複数のタブやウィンドウの間で通信する方法を探していました(同一ドメイン内。 CORS を、痕跡を残さずに行うことができます。いくつかの解決策がありました。
最初の方法は、おそらく最悪の解決策です。現在のウィンドウからウィンドウを開く必要があり、ウィンドウを開いている間だけ通信が可能です。もし、いずれかのウィンドウでページを再読み込みすると、ほとんどの場合、通信が途絶えます。
2つ目のpostMessageを使う方法は、おそらくクロスオリジン通信を可能にしますが、1つ目の方法と同じ問題が生じます。ウィンドウ・オブジェクトを維持する必要があるのです。
3番目の方法は、クッキーを使用して、ブラウザにいくつかのデータを保存します。これは、効果的に同じドメイン上のすべてのウィンドウにメッセージを送信するように見えますが、問題は、すべてのタブがすでに"メッセージ"を読んだかどうかをクリーンアップ前に知ることができないことです。定期的にクッキーを読み込むために、ある種のタイムアウトを実装しなければなりません。さらに、クッキーの最大長は4キロバイトという制限があります。
4つ目の解決策は、localStorageを使用することで、クッキーの制限を克服し、さらにイベントを使用してリッスンすることができるようになったようです。その使い方は、採用された回答に記載されています。
2018年現在、受け入れた回答はまだ機能しますが、モダンブラウザのための新しいソリューション、BroadcastChannelを使用する方法があります。BroadcastChannelを使用して、タブ間で簡単にメッセージを送信する方法を説明する簡単な例については、他の回答を参照してください。
どのように解決するのですか?
ブロードキャストチャンネルを使用するとよいでしょう。以下の他の回答を参照してください。それでもまだタブ間の通信にlocalstorageを使用したい場合は、この方法で行ってください。
あるタブが他のタブにメッセージを送信したときに通知を受けるには、単に 'storage' イベントをバインドする必要があります。すべてのタブで、次のようにしてください。
$(window).on('storage', message_receive);
機能
message_receive
は、他のタブでlocalStorageの値を設定するたびに呼び出されます。イベントリスナーはlocalStorageに新しく設定されたデータも含むので、localStorageオブジェクト自体をパースする必要はありません。これは非常に便利な機能で、値を設定した直後にリセットすることで、痕跡を効果的に消すことができます。以下はメッセージングのための関数です。
// use local storage for messaging. Set message in local storage and clear it right away
// This is a safe way how to communicate with other tabs while not leaving any traces
//
function message_broadcast(message)
{
localStorage.setItem('message',JSON.stringify(message));
localStorage.removeItem('message');
}
// receive message
//
function message_receive(ev)
{
if (ev.originalEvent.key!='message') return; // ignore other keys
var message=JSON.parse(ev.originalEvent.newValue);
if (!message) return; // ignore empty msg or msg reset
// here you act on messages.
// you can send objects like { 'command': 'doit', 'data': 'abcd' }
if (message.command == 'doit') alert(message.data);
// etc.
}
これで、タブが onstorage イベントにバインドされ、これら 2 つの関数が実装されると、他のタブにメッセージをブロードキャストして、たとえば、次のように呼び出すことができます。
message_broadcast({'command':'reset'})
全く同じメッセージを二度送信しても、伝搬されるのは一度だけなので、メッセージを繰り返す必要がある場合は、以下のように一意の識別子を追加してください。
message_broadcast({'command':'reset', 'uid': (new Date).getTime()+Math.random()})
また、メッセージをブロードキャストした現在のタブは実際にはメッセージを受信せず、同じドメイン上の他のタブまたはウィンドウのみがメッセージを受信することを覚えておいてください。
setItem()の後にremoveItem()を呼び出した直後に、ユーザーが別のウェブページをロードしたり、タブを閉じたりしたらどうなるのか、という質問があるかもしれません。私自身のテストでは、ブラウザは関数全体が終了するまでアンロードを保留にします。
message_broadcast()
が終了します。非常に長い for() サイクルを入れてテストしてみましたが、やはりサイクルが終了するのを待ってから閉じました。もしユーザーがその間にタブを閉じてしまったら、ブラウザはメッセージをディスクに保存するのに十分な時間がないでしょうから、この方法は痕跡を残さずにメッセージを送信する安全な方法だと思います。
関連
-
[解決済み】TypeError: 'undefined'はオブジェクトではありません。
-
[解決済み] 解決済み】clearInterval()が動作しない [重複] [重複]
-
[解決済み】最大呼び出しスタックサイズ超過エラーとその修正方法とは?
-
[解決済み】JavaScript ランタイムエラー:'$'が未定義です。
-
[解決済み】XMLパースエラー:ルート要素が見つからない コンソールの場所 FF
-
[解決済み] let "と "var "の使い分けは?
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] JavaScriptで2つの数値の間の乱数を生成する
-
[解決済み] Bowerとnpmの違いは何ですか?
-
[解決済み] JSONウェブトークンの無効化
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】document.getElementByIDは関数ではありません。
-
[解決済み】Javascriptのコールバック関数がFirefoxで「Callback is not a function」というエラーを投げる
-
[解決済み】SyntaxError: 'import' と 'export' は 'sourceType: module' とだけ表示されるかもしれない - Gulp
-
[解決済み】JavaScriptのボタンonclickが機能しない
-
[解決済み】Babel NodeJS ES6: SyntaxError: 予期しないトークンのエクスポート
-
[解決済み】SyntaxError: 期待された式が、'<'を得た。
-
[解決済み】ETIMEDOUTエラーの対処方法は?
-
[解決済み】Vueが定義されていない
-
[解決済み】Javascript、[オブジェクトHTMLInputElement]を表示中。]
-
[解決済み] JavaScriptを使ったブラウザのタブ/ウィンドウ間の通信 [重複]について