我在“外国”页面(不同的域等)上的iframe内运行应用程序。允许iframe和&之间的一些基本通信。父母,我在父页面上加载了我的一些脚本,并使用postMessage
进行跨文档消息传递。
大多数情况下,此通信按预期工作,但有时我会看到一些错误报告给我的错误跟踪工具,但无法弄清楚它们发生的原因。
以下是一些示例代码:
PluginOnParent.js
// ...
window.addEventListener('message', function(e) {
// Check message origin etc...
if (e.data.type === 'iFrameRequest') {
e.source.postMessage({
type: 'parentResponse',
responseData: someInterestingData
}, e.origin);
}
// ...
}, false);
// ...
AppInsideIFrame.js
// ...
var timeoutId;
try {
if (window.self === window.top) {
// We're not inside an IFrame, don't do anything...
return;
}
} catch (e) {
// Browsers can block access to window.top due to same origin policy.
// See http://stackoverflow.com/a/326076
// If this happens, we are inside an IFrame...
}
function messageHandler(e) {
if (e.data && (e.data.type === 'parentResponse')) {
window.clearTimeout(timeoutId);
window.removeEventListener('message', messageHandler);
// Do some stuff with the sent data
}
}
timeoutId = window.setTimeout(function() {
errorTracking.report('Communication with parent page failed');
window.removeEventListener('message', messageHandler);
}, 500);
window.addEventListener('message', messageHandler, false);
window.parent.postMessage({ type: 'iFrameRequest' }, '*');
// ...
当超时命中并报告错误时,会发生什么?
更多信息&我的想法:
答案 0 :(得分:1)
问题似乎出现在 PluginOnParent.js 中,您将在此处发送回复。而不是使用" e.origin" (在开发人员工具中检查后返回" null") - 尝试使用文字' *',如下面关于 postMessage 用法(在 targetOrigin 的描述中):
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
另外,作为奖励,我只是在两个不同的域中测试了它,它也可以。我将Parent.html放在一个域名网络服务器上,并将iframe的src更改为一个完全不同的域名上的child.html,他们一起沟通得很好。
<强> Parent.html 强>
<html>
<head>
<script type="text/javascript">
function parentInitialize() {
window.addEventListener('message', function (e) {
// Check message origin etc...
if (e.data.type === 'iFrameRequest') {
var obj = {
type: 'parentResponse',
responseData: 'some response'
};
e.source.postMessage(obj, '*');
}
// ...
})
}
</script>
</head>
<body style="background-color: rgb(72, 222, 218);" onload="javascript: parentInitialize();">
<iframe src="child.html" style="width: 500px; height:350px;"></iframe>
</body>
</html>
&#13;
<强> Child.html 强>
<html>
<head>
<script type="text/javascript">
function childInitialize() {
// ...
var timeoutId;
try {
if (window.self === window.top) {
// We're not inside an IFrame, don't do anything...
return;
}
} catch (e) {
// Browsers can block access to window.top due to same origin policy.
// See http://stackoverflow.com/a/326076
// If this happens, we are inside an IFrame...
}
function messageHandler(e) {
if (e.data && (e.data.type === 'parentResponse')) {
window.clearTimeout(timeoutId);
window.removeEventListener('message', messageHandler);
// Do some stuff with the sent data
var obj = document.getElementById("status");
obj.value = e.data.responseData;
}
}
timeoutId = window.setTimeout(function () {
var obj = document.getElementById("status");
obj.value = 'Communication with parent page failed';
window.removeEventListener('message', messageHandler);
}, 500);
window.addEventListener('message', messageHandler, false);
window.parent.postMessage({ type: 'iFrameRequest' }, '*');
// ...
}
</script>
</head>
<body style="background-color: rgb(0, 148, 255);" onload="javascript: childInitialize();">
<textarea type="text" style="width:400px; height:250px;" id="status" />
</body>
</html>
&#13;
希望有所帮助!
答案 1 :(得分:1)
大部分时间此通信都按预期工作,但有时我 看到我的错误跟踪工具报告的一些错误,无法想象 了解他们为什么会这样。
当超时命中并报告错误时,会发生什么?
我自己无法控制父页面
不确定函数errorTracking.report
在调用时的作用,但似乎没有出现与message
事件相关的实际错误?
500毫秒的超时只是我选择的一些神奇数字 以为是完全安全的......
duration
设置为500
,setTimeout
事件可能会在message
点击window
之前被调用。
timeoutId = window.setTimeout(function() {
errorTracking.report('Communication with parent page failed');
window.removeEventListener('message', messageHandler);
}, 500);
将duration
的{{1}}调整为更长的持续时间。
或者替换onerror
处理程序或window.addEventListener
代替setTimeout
注释
当脚本中出现语法(?)错误时,从a加载 different origin,不会报告语法错误的详细信息 防止泄露信息(见bug 363897)。而是错误 据报道只是“脚本错误”。可以覆盖此行为 某些浏览器使用crossorigin上的属性并拥有 服务器发送相应的
CORS
HTTP响应头。一个 解决方法是隔离“脚本错误”。并知道这一点处理它 错误详细信息只能在浏览器控制台中查看而不能查看 可通过JavaScript访问。
例如
setTimeout
在不同的上下文或来源之间进行通信时处理任何实际错误。
在// handle errors
onerror = function messageErrorHandlerAtAppInsideIFrame(e) {
console.error("Error at messageErrorIndex", e)
}
postMessage
事件load
上使用iframe
与父message
的{{1}}处理程序进行通信。