我有一个应用程序在“外部”页面(不同域等)的 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' }, '*');
// ...
当超时并报告错误时,会发生什么?
我的一些更多信息和想法:
- 我自己无法控制父页面
- 这似乎不是一般的“配置”问题(CORS 等),因为错误发生在大多数时间工作的同一页面上
- 我们根本不支持 IE
- My error reporting tool reports a multitude of different browsers amongst which are the latest versions of them (FF 49, Chrome 43 on Android 5, Chrome 53 on Win and Android 6, Mobile Safari 10, ...)
- 500 毫秒的超时只是我选择的一个神奇数字,我认为它是完全安全的......
问题似乎出在你的PluginOnParent.js,您将回复发送到的位置。不要使用“e.origin”(在开发人员工具中检查后返回“null”)——尝试使用文字“*”,如以下文档中所述发布消息用法(在描述中目标原点):
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
另外,作为奖励,我刚刚在两个不同的域中测试了它,它也有效。我将 Parent.html 放在一个域的 Web 服务器上,并将 iframe 的 src 更改为完全不同的域上的 child.html,它们可以很好地通信。
父级.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>
孩子.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>
希望有帮助!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)