Détecter si PostMessage peut envoyer des objets?

Je recherche une bonne façon de détecter si PostMessage dans le navigateur prend en charge l'envoi et la réception d'objets ou simplement des chaînes. Je pense que quelqu'un là-bas doit avoir écrit quelque chose qui fait cela, mais je n'ai pas réussi à trouver une solution.

J'utilise PostMessage pour envoyer des données vers / depuis un WebWorker. Tout en détectant si le navigateur prend en charge les travailleurs est simple, détecter si les objets peuvent être envoyés via PostMessage s'est révélé plus difficile.

J'aimerais écrire une fonction de détection simple. Donc, si le navigateur prend en charge l'envoi d'objets pour l'utiliser. Si seulement les chaînes sont autorisées, je peux recommencer à utiliser JSON.stringify (). Je vais probablement attribuer la fonction à un test dojo / a test (bien que cela ne soit pas pertinent pour la question / réponse).

Qu'ont fait d'autres personnes pour résoudre ce problème? Tout conseil serait génial, je suis nouveau chez WebWorkers et PostMessage. Merci d'avance.

J'ai trouvé un moyen encore plus simple de détecter si PostMessage ne supporte que les chaînes ou s'il supporte d'autres types. Il suffit d'ajouter une méthode customString sur l'objet. Lorsque vous essayez d'envoyer un objet avec postMessage dans IE8 et IE9, ils seront convertis en une chaîne avec la méthode toString sur l'objet. Étant donné que les navigateurs qui prennent en charge les objets d'envoi n'appellent pas à String, nous pouvons utiliser cela à notre avantage. Ce test n'est pas asynchrone, donc vous obtiendrez le résultat instantanément. N'ont pas testé cela avec des web-workers, mais je suppose que vous pouvez utiliser la même technique.

 var onlyStrings = false; try{window.postMessage({toString:function(){onlyStrings=true;}},"*");}catch(e){} console.log("Browser only supports postMessage with strings? " + onlyStrings); 

Testé dans IE8, IE9, IE10 et la dernière version de Chrome, Firefox, Safari et Opera: http://jsbin.com/igowoFaj/1/edit?js,console

Mise à jour: un test BrowserScope a été testé avec beaucoup plus de tests et de navigateurs. La conclusion est qu'il est sûr d'envoyer des objets clonables, des tableaux, des nombres, des données de pixels et des tampons de réseau si onlyStrings est false . En théorie, tous les navigateurs qui permettent d'envoyer des objets devraient utiliser l' algorithme de clone structuré , mais le navigateur Android et Opera Mobile ont des caprices. Le résultat du test BrowserScope est un peu difficile à lire, car un 0 pour send_xxx n'est problématique que si le navigateur a effectivement un support pour ce type, vérifiez également support_xxx. Si elles sont égales, c'est correct, mais c'est un bug si le navigateur a un support mais ne peut pas envoyer (lorsque OnlyStrings est faux).

Je voulais savoir la même chose. J'ai créé ce script pour détecter si un objet peut être transmis dans PostMessage par un rappel simple à la fenêtre actuelle. Vous verrez IE 9 retourner faux, IE 10 renvoie vrai.

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); 

Vous pouvez essayer d'effectuer une action avant de reprendre votre script. Vous pourriez essayer ceci:

Dummy_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); } 

postMessage fonctionne également entre iframe s; En supposant que le comportement est le même entre les travailleurs et les cadres, vous devriez essayer ce qui suit ou quelque chose comme ça:

 <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> 

Vous devrez peut-être remplacer la console ou console.log pour pouvoir voir les résultats, mais sur Chrome, cela m'obtient

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

Lorsque je l'enregistre dans un fichier local et que je l'ouvre.

La version jsfiddle (et la version qui utilise un travailleur réel) sont laissés comme un exercice pour le lecteur. :)