2012-12-07 14 views
5

私は、ブラウザのpostMessageがオブジェクトまたは単なる文字列の送受信をサポートしているかどうかを検出するきちんとした方法を探しています。私はそこの誰かがこれを行う何かを書いているに違いないが、私は解決策を見つけることができていないと考えている。postMessageがオブジェクトを送信できるかどうかを検出しますか?

私はWebWorkerとの間でデータをやりとりするためにpostMessageを使用しています。ブラウザーがワーカーをサポートしているかどうかを検出するのは簡単ですが、postMessage経由でオブジェクトを送信できるかどうかを検出することは困難です。

私は簡単な検出機能を書いています。したがって、ブラウザがそれを使用するオブジェクトの送信をサポートしている場合。文字列のみが許可されている場合、私はJSON.stringify()を使用することに代わることができます。おそらく関数をdojo/hasテストに割り当てます(これは質問/回答には関係ありませんが)。

この問題を解決するために他の人が行ったことはありますか?どんなアドバイスも素晴らしいだろう、私はWebWorkersとpostMessageの両方に新しい。前もって感謝します。

+0

私からのダムの質問 - あなたは 'postMessage'を同じウィンドウにできますか? – Ian

+0

@イアン...何ですか? WebWorkerは(疑似)スレッドを作成するクラスです。あなたは基本的にexternのjavascriptファイルを実行することができますが、そのページのjavascriptは完璧に動作し続けます。 'postMessage'はあなたがそのスレッドと通信できるようにします。それはまったく異なる窓とは関係がありません。 –

+0

最初の文は 'postMessage'でメッセージを送信することについて話します。私は 'postMessage'を調べて、他のウィンドウにメッセージを送ることについて話します(私が覚えているように)。あなたがWeb Workersと話しているという事実を無視して、なぜテストコールを設定しないのですか?私は彼らのコミュニケーションが異なると思っていますが、現在のウィンドウで 'onmessage'のリスナーを設定し、' {} 'を渡すと' typeof'をチェックして文字列ではなくオブジェクトであるかどうかを確認します。 – Ian

答えて

18

私はそれが他の種類をサポートしている場合のpostMessageは文字列のみをサポートしているかどうかを検出するためのより簡単な方法を発見しました。オブジェクトにカスタムのtoStringメソッドを追加するだけです。 IE8とIE9でpostMessageでオブジェクトを送信しようとすると、オブジェクトのtoStringメソッドで文字列に変換されます。送信オブジェクトをサポートするブラウザはtoStringを呼び出さないので、これを私たちの利点に利用することができます。このテストは非同期ではありませんので、すぐに結果を得ることができます。これをWebワーカーとテストしていないのですが、同じテクニックを使用できると思います。

IE8、IE9、IE10とChromeは、Firefox、SafariとOperaの最新バージョンでテスト
var onlyStrings = false; 
try{window.postMessage({toString:function(){onlyStrings=true;}},"*");}catch(e){} 

console.log("Browser only supports postMessage with strings? " + onlyStrings); 

http://jsbin.com/igowoFaj/1/edit?js,console

更新:より多くのテストやブラウザでBrowserScope testをしました。結論は、onlyStringsfalseの場合、クローン可能なオブジェクト、配列、数値、ピクセルデータ、および配列バッファを送信することは安全です。理論的には、オブジェクトの送信を許可するすべてのブラウザはstructured clone algorithmを使用する必要がありますが、AndroidブラウザとOpera Mobileには癖があります。 BrowserScopeのテスト結果は、読みにくいです。なぜなら、send_xxxの0は、ブラウザが実際にそのタイプをサポートしている場合にのみ問題になるからです。それで、support_xxxもチェックしてください。それらが等しい場合、それは問題ありませんが、ブラウザがサポートしていても送信できない場合(onlyStringがfalseの場合)はバグです。

2

スクリプトを再開する前に、アクションを実行することができます。あなたはこれを試みることができる:

dummy_task.js

self.onmessage = function(event) { 
    self.postMessage(event.data); 
}; 

workerSupportObject(callback); 

function workerSupportObject(callback) { 
    var callbackIsCalled = false; // to make sure callback isn't run twice 
    var worker = new Worker('dummy_task.js'); // create a worker 

    // create event 
    worker.onmessage = function(event) { 
     // if the value is the same as we sent, it probably works 
     if(!callbackIsCalled) callback.call(null, event.data.value === 'dummy'); 
     callbackIsCalled = true; 
    }; 

    try { 
     // send dummy JSON data 
     worker.postMessage({'value': 'dummy'}); 
    } catch(e) { 
     // oh... an error... clearly that's a no. 
     if(!callbackIsCalled) callback(null, false); 

     callbackIsCalled = true; 
    } 
} 

function callback(objectSupported) { 
    console.log('Worker supports objects: ', objectSupported); 
} 
+0

ありがとう、これはかなりうまくいくように思えました。これをコールバックなしで行うことはできませんが、これをhas()関数に割り当てることができないので、残念です。構造体が存在しないことを保証するためには、可用性がテストされた後にのみ呼び出されます。しかし、ここで行っていることのイベントベースの性質を考えると、コールバックなしでこれを行うことはおそらく不可能です。ご協力いただきありがとうございます。 –

0

postMessageiframe秒の間に動作するJavaScript。あなたはそれのように、以下のか何かを試してみてください、行動は労働者とフレーム間で同じであると仮定すると:

<html> 
    <body> 
     <iframe id='if'> 

     </iframe> 
     <script> 
     var iframe = document.getElementById('if'); 
     var iframeScript = iframe.contentDocument.createElement("script"); 
     iframeScript.appendChild(
      iframe.contentDocument.createTextNode(
       'window.addEventListener("message", function(e) {console.log(e.data);}); console.log("listener attached");')); 
     iframe.contentDocument.body.appendChild(iframeScript); 
     iframe.contentWindow.postMessage("asdf", "*"); 
     iframe.contentWindow.postMessage({'whatAmI': 'an object, maybe?'}, "*"); 
     </script> 
    </body> 
</html> 

あなたは結果を見ることができるようにするコンソールまたはにconsole.logを交換する必要があるかもしれませんが、クロムに、これは私を得ます

listener attached about:blank (1):1 
asdf about:blank (1):1 
Object {whatAmI: "an object, maybe?"} about:blank (1):1 

私はそれをローカルファイルに保存して開きます。

jsfiddleバージョン(および実際の作業者を使用するバージョン)は、読者の練習として残されています。 :)

3

私は同じことを知りたがっていました。このスクリプトを作成して、現在のウィンドウへの単純なコールバックによってオブジェクトがpostMessageに渡されるかどうかを検出しました。 IE 9がfalseを返し、IE 10がtrueを返します。

http://jsfiddle.net/milesplit/DvqqH/

var supportsPostObject = false; 

(function(){ 
    var callback = function(e) { 
     supportsPostObject = (typeof(e.data)!='string'); 
    }; 
    (window.addEventListener) ? 
     window.addEventListener('message', callback) : 
     window.attachEvent('onmessage', callback); 
    ('postMessage' in window) && window.postMessage({}, '*'); 
})(); 

setTimeout(function(){ 
    alert(supportsPostObject); 
}, 0); 
関連する問題