我有一个带有iframe的Web应用程序,需要与其托管页面进行通信。 iframe和主机位于不同的域和协议上(iframe是https,主页面是http)。我使用postMessage从外部页面获取一小部分状态(用户跟踪)到iframe。
当加载iframe时,它会向首页发送一条短信,要求访问者:
if ($.w.top != $.w) $.f.postMessage($.w.top, 'Get visitorId');
($。f.postMessage(w,m)只是postMessage的包装器,如果typeof w.postMessage ==='undefined',则什么都不做。在外部页面上,我们有一个消息监听器:
// Set up event listener so that we can respond when any iframes
// inside of us ask for our visitorId
$.f.listen($.w, 'message', giveVisitorId);
function giveVisitorId(event) {
$.w['zzzzz'] = event.source;
if (event.data === 'Get visitorId') {
alert('about to reply from '+window.location.href+' with visitorid, typeof event.source.postMessage is ' + typeof(event.source.postMessage));
event.source.postMessage('visitorId=' + $.v.visitorId, '*');
}
}
内部框架有一个为响应注册的侦听器:
$.f.listen($.w, 'message', receiveVisitorId);
function receiveVisitorId(event) {
alert('receiveVisitorId called with: ' + event.data + ' in window '+window.location.href);
var s = event.data.split('=');
if (s[0] === 'visitorId' && s.length === 2) {
$.v.visitorId = s[1];
$.w.clearTimeout(giveUp);
rest();
}
}
这一切都适用于OSX上的chrome和firefox(当加载iframe时,我们会收到两个警报,一个来自receiveVisitorId,另一个来自giveVisitorId);但是在XP上的IE8上我们只得到第一个警报(来自giveVisitorId)。
这很奇怪,因为似乎postMessage出去工作而进入的那个没有;真正令人困惑的是,如果我们进入控制台并运行zzzzz.postMessage('hi', '*')
,则receiveVisitorId中的警报就像预期的那样发生! (注意我们在window.zzzzz中保存了event.source)。
有没有人知道为什么会这样?
PS:$ .w.listen和$ .w.postMessage的定义,供参考:
listen: function (el, ev, fn) {
if (typeof $.w.addEventListener !== 'undefined') {
el.addEventListener(ev, fn, false);
}
else if (typeof $.w.attachEvent !== 'undefined') {
el.attachEvent('on' + ev, fn);
}
},
postMessage: function(w, m) {
if (typeof w.postMessage !== 'undefined') {
w.postMessage(m, "*");
}
},
答案 0 :(得分:2)
我们解决了。问题是我们在内部iframe中$.f.listen
之后调用了$.f.postMessage
;因此,当外窗向内部发布消息时,侦听器尚未附加。我不知道为什么在IE中发生这种情况而不是chrome或firefox,但我们只是将它归结为浏览器之间的时序差异。