8

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

postMessageを使用してWebWorkerとの間でデータを送受信しています。ブラウザがワーカーをサポートしているかどうかの検出は簡単ですが、オブジェクトがpostMessageを介して送信できるかどうかの検出はより困難であることが証明されています。

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

この問題を解決するために他の人は何をしましたか?どんなアドバイスも素晴らしいでしょう、私はWebWorkersとpostMessageの両方に不慣れです。前もって感謝します。

4

4 に答える 4

22

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

var onlyStrings = false;
try{window.postMessage({toString:function(){onlyStrings=true;}},"*");}catch(e){}

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

IE8、IE9、IE10、および最新バージョンのChrome、Firefox、Safari、Operaでテスト済み:http://jsbin.com/igowoFaj/1/edit?js、 console

更新:BrowserScopeテストをさらに多くのテストとブラウザーで行いました。結論として、がの場合、クローン可能なオブジェクト、配列、数値、ピクセルデータ、および配列バッファを安全に送信できonlyStringsますfalse。理論的には、オブジェクトの送信を許可するすべてのブラウザーは構造化クローンアルゴリズムを使用する必要がありますが、AndroidブラウザーとOperaMobileには癖があります。BrowserScopeのテスト結果は少し読みにくいです。send_xxxの0は、ブラウザーが実際にそのタイプをサポートしている場合にのみ問題になるため、supports_xxxも確認してください。それらが等しい場合は問題ありませんが、ブラウザがサポートしているのに送信できない場合(onlyStringsがfalseの場合)はバグです。

于 2013-12-23T12:11:00.137 に答える
3

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

ダミー_task.js

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

javascript

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);
}
于 2012-12-07T11:28:10.093 に答える
3

同じことを知りたかった。このスクリプトを作成して、現在のウィンドウへの単純なコールバックによってオブジェクトがpostMessageで渡されるかどうかを検出しました。IE 9はfalseを返し、IE10は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);
于 2013-03-09T06:36:36.380 に答える
0

postMessageiframes間でも機能します。動作がワーカーとフレームで同じであると仮定すると、次のようなものを試す必要があります。

<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またはconsole.logを置き換える必要があるかもしれませんが、Chromeではこれで問題が解決します

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

ローカルファイルに保存して開いたとき。

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

于 2013-01-08T18:39:00.970 に答える