Javascript 检测postMessage是否可以发送对象?
我正在寻找一种简洁的方法来检测浏览器中的postMessage是否支持对象的发送和接收,还是仅支持字符串。我想一定有人写了这样的东西,但我没有找到解决办法 我正在使用postMessage向WebWorker发送数据或从WebWorker发送数据。虽然直接检测浏览器是否支持worker,但事实证明,检测对象是否可以通过postMessage发送更加困难 我想写一个简单的检测函数。因此,如果浏览器支持发送对象,就可以使用它。如果只允许使用字符串,我可以回退到使用JSON.stringify()。我可能会将该函数分配给dojo/has测试(尽管这与问题/答案无关)Javascript 检测postMessage是否可以发送对象?,javascript,html,dojo,web-worker,postmessage,Javascript,Html,Dojo,Web Worker,Postmessage,我正在寻找一种简洁的方法来检测浏览器中的postMessage是否支持对象的发送和接收,还是仅支持字符串。我想一定有人写了这样的东西,但我没有找到解决办法 我正在使用postMessage向WebWorker发送数据或从WebWorker发送数据。虽然直接检测浏览器是否支持worker,但事实证明,检测对象是否可以通过postMessage发送更加困难 我想写一个简单的检测函数。因此,如果浏览器支持发送对象,就可以使用它。如果只允许使用字符串,我可以回退到使用JSON.stringify()。我
其他人做了什么来解决这个问题?任何建议都很好,我对网络工作者和postMessage都是新手。提前感谢。您可以在恢复脚本之前尝试执行操作。你可以试试这个: 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
也在iframe
s之间工作;假设工人和框架之间的行为相同,则应尝试以下操作或类似操作:
<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>
当我将它保存到本地文件并打开它时
JSFIDLE版本(以及使用实际工作程序的版本)留给读者作为练习<我想知道同样的事情。我创建这个脚本是为了检测一个对象是否可以通过一个简单的回调在postMessage中传递到当前窗口。你会看到IE9返回false,IE10返回true
我发现了一种更简单的方法来检测postMessage是否只支持字符串或是否支持其他类型。只需在对象上添加自定义toString方法。在IE8和IE9中尝试发送带有postMessage的对象时,它们将通过对象上的toString方法转换为字符串。因为支持发送对象的浏览器不调用toString,所以我们可以利用它。此测试不是异步的,因此您将立即得到结果。我还没有对web workers进行过测试,但我想您可以使用相同的技术
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中测试:
更新:做了一个有更多测试和浏览器的测试。结论是,如果
onlyStrings
为false
,则发送可克隆对象、数组、数字、像素数据和数组缓冲区是安全的。理论上,所有允许发送对象的浏览器都应该使用,但Android浏览器和Opera Mobile有其独特之处。BrowserScope测试结果有点难以读取,因为只有当浏览器实际支持该类型时,发送\u xxx的0才有问题,所以检查也支持\u xxx。如果它们相等,这没关系,但如果浏览器有支持但无法发送(当onlystring为false时),这就是一个错误。我问了一个愚蠢的问题-你能postMessage
到同一个窗口吗?@Ian。。。什么?WebWorker是一个创建(伪)线程的类。您基本上可以运行一个externJavaScript文件,而该页面中的javascript继续完美地运行postMessage
允许您与该线程通信。它与不同的窗口没有任何关系。您的第一句话谈到使用postMessage
发送消息。我查找postMessage
,它谈到了向其他窗口发送消息(我记得)。忽略您正在与网络工作者交谈的事实,为什么不设置一个测试呼叫呢?我猜他们的交流是不同的,但是如果你在当前窗口中为onmessage
设置一个侦听器并传入{}
…只需检查的类型,看看它是否是一个对象而不是字符串。谢谢,这似乎工作得很好。不幸的是,在没有回调的情况下,这是无法完成的,因为它使得能够将其分配给has()函数无效。没有适当的结构来确保has()只在测试可用性之后才被调用。然而,考虑到我们在这里所做的事情是基于事件的,如果没有回调,这可能是不可能的。谢谢你的帮助。
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);
var onlyStrings = false;
try{window.postMessage({toString:function(){onlyStrings=true;}},"*");}catch(e){}
console.log("Browser only supports postMessage with strings? " + onlyStrings);