これまでのところ、一方のウィンドウが単一の種類のメッセージを送信し、もう一方のウィンドウがメッセージを単一の方法でのみ解釈するポストメッセージのチュートリアルしか見ていません。
ウィンドウ間でさまざまな種類のインタラクションが必要な場合、ポストメッセージでそれを処理できますか?
それは、ポストメッセージが行うことになっていることの粒子に反していますか?
たとえば、カスタムコールバックを送受信できるようにしたい場合はどうすればよいですか?
マルチパートメッセージをpostMessage
ハンドラーに渡す方法はいくつかあります。 1つ目(そして「クリーン」ではない方法)は、区切り文字を使用してから、データをストリングで渡す方法です。
ユーザーID、アクション、およびユーザー名を渡したいとしましょう。文字列は次のようになります。
54|do_logout|chris
postMessage
ハンドラー内で、渡されるデータは|
文字のsplit
( docs )にすることができ、メッセージの各セグメントを必要に応じて使用できます。
文字列を手動で作成/分割する代わりに、JSON( docs )を使用してオブジェクトを片側の文字列に変換し、JSONを使用してハンドラー内のオブジェクトに変換する方法もあります。
var pass_data = {
'name':'Chris',
'id':54,
'action':'do_logout'
};
target_window.postMessage(JSON.stringify(pass_data), "http://www.example.net");
...次にハンドラーで:
function (event) {
var pass_data = JSON.parse(event.data);
}
ただし、JSON
オブジェクトはすべてのユーザーエージェント、特に古いものでは提供されていないため、必ずテストしてください。 JSONサポートをシムするためのサードパーティライブラリはたくさんありますので、完全に採用されていないことを恐れないでください。JSONは間違いなく安全な「前進」標準です。
そのオブジェクトをすぐに渡すことができればもっといいのではないでしょうか。さて、Firefox 6( source )を見つめていると、ポストメッセージハンドラーに渡すデータはオブジェクトである可能性があります。オブジェクトはシリアル化されるため、その面でいくつかの懸念がありますが、次のようになります。
var pass_data = {
'name':'Chris',
'id':54,
'action':'do_logout'
};
target_window.postMessage(pass_data, "http://www.example.net");
もう少しいいですね残念ながら、現在のバージョンのIEは文字列のみを処理します。 IE 10のpostMessage
に関する将来の計画についての議論は見つかりませんでした。さらに、IE 8/9には、フレーム以外のpostMessage
を壊す既知のバグがあります。 ( ソース )。
質問の特定の側面、つまりコールバックについて説明します。関数名でコールバックを渡すことができない限り、関数を渡す方法はありません。匿名関数はありません。これは、データが実際にハンドラーに渡される方法に関連しています。実際には、データとしてのオブジェクトのサポートは「ありません」。舞台裏では、ブラウザが渡されたオブジェクトを文字列に変換します(シリアル化)。
つまり、オブジェクトを渡すことは、渡す前にオブジェクトをstringify
にJSONを使用することとまったく同じであることを理解する必要があります。シリアル化/非シリアル化するのはあなた次第です。
ここでのポイント:
ドキュメントとリファレンス
window.postMessage
: https://developer.mozilla.org/en/DOM/window.postMessageString.split
: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/splitJSON.stringify
: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringifyJSON.parse
: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/parse私が見つけたNiceプラグインがあります npmは "silver-bullet"と呼ばれます 。コールバックを使用してpostMessageを実行し、eventEmitterを使用して特定のイベントも取得します。それは非常にうれしいです。
しかし、これを実装するには、次のようにします...
phostMessage(iframe, someObj, callback);
あなたはこれをしなければなりません:
これは、その非常に基本的なデモです。
var callbacks = {};
// when receiving messages
window.addEventListener('message', function(ev) {
// todo: add Origin check
if (!ev.data)
return;
var message;
try {
message = JSON.parse(ev.data);
} catch (ex) {
console.error(ex);
}
// ignore messages not having a callback ID
if (!message || !message.callbackId)
return;
// we are the sender getting the callback
if (callbacks[message.callbackId]) {
callbacks[message.callbackId](message);
delete callbacks[message.callbackId];
return;
}
// we are the receiver so we respond with the callback ID
// todo: restrict who can receive message (last param)
iframe.contentWindow.postMessage(JSON.stringify(message), '*');
});
// when sending messages
function phostMessage(iframe, obj, callback) {
obj.eventId = Math.random();
callbacks[obj.eventId] = callback;
// todo: restrict who can receive message (last param)
iframe.contentWindow.postMessage(JSON.stringify(obj), '*');
}
私はこの概念をもう少し進めて、メッセージハンドラールックアップを使用します。メッセージには、メッセージを呼び出して渡すための目的のハンドラー関数名があります。メッセージハンドラーはコールバックも受け取り、完了時にコールバックを起動します。コールバックには、ネイティブの投稿メッセージを再度呼び出して、受信したコールバックIDを送り返すという単純なロジックがあります。
したがって、メッセージイベント処理のコードの最終行は次のようになります。
if (messageHandler[message.handler])
messageHandler[message.handler](message, function() {
iframe.contentWindow.postMessage(JSON.stringify(message), '*');
});
else
iframe.contentWindow.postMessage(JSON.stringify(message), '*');
これにより、非同期のものが発生します。
私は最近同じ問題に直面しました。何時間も検索した後、私は post-robot に出くわしました。これはPaypal
によって開発され、postMessage
のコールバックを含む私の問題のほとんどを解決しました。
また、ペイロード内での関数の受け渡しもサポートしています。
ここで紹介をチェックできます ポストロボットの紹介
実際のコードを渡さずにtriggerコールバックを行う簡単な方法は次のとおりです。
ターゲット
var callbacks = {
myCallback: function() { doSomething(); }
};
window.addEventListener('message', function (ev) {
// Origin checking etc
callbacks[ev.data]();
}, false);
ソース
target.postMessage('myCallback', 'http://www.example.com');