HTML 5 PostMessage / Detect iFrame无法加载

时间:2011-07-19 20:03:39

标签: javascript jquery asp.net html5

我们有一些代码正在利用HTML 5中的新postMessage功能来解决跨域通信问题。我正试图找到一种方法来检测我是否将消息发布到正确加载其内容的iFrame。如果帧无法正确加载,postMessage不会知道这一点,并且很乐意将消息发布到无响应的帧中(我假设消息正在传递到帧,无论是否加载了内容)。

这是我们的工作流程:

  1. 用户加载http://www.a.com/specialpage.aspx
  2. a.com/specialpage.aspx依次加载子iFrame,将其源设置为来自其他域的代理页面,例如http://www.b.com/lookatmyproxy.htm
  3. 用户执行某些操作,单击按钮
  4. window.postMessage用于将消息发布到子帧,其中(希望)由加载帧的代理(b.com/lookatmyproxy.htm)拾取。收到邮件后,将验证,处理邮件,并将回复发回给父框架(a.com/specialpage.aspx)。
  5. 向用户显示他们的行动结果,每个人都很高兴。
  6. 问题的情况是,如果b.com关闭且代理无法加载到iFrame中,postMessage将只会触发并忘记,并且父框架永远不会收到错误或任何类型的回复。 iframe的安全问题和性质似乎阻止我检查框架内容或状态,以确定代理是否正确加载。我可以在a.com和b.com之间放置一个带有一些超时逻辑的继电器(a.com发布到a.com/relay,然后发布到b.com/proxy等) ,但这似乎过于复杂。

    我有没有办法检查iFrame并告诉它的内容是否正确加载,或者检测到postMessage是否正在传送到源无法加载的帧?

1 个答案:

答案 0 :(得分:2)

这不是最干净的答案,但我能够解决我的问题。我发现的是一些旧文档,虽然安全性不允许您从其他帧读取信息,但您可以调用某些函数。在较旧的浏览器中,这用于欺骗帧以设置彼此的url片段并导致操作发生。这里有一个很好的参考:

http://softwareas.com/cross-domain-communication-with-iframes

由于允许使用postMessage,我的代理所做的第一件事就是将“已加载”的消息发布到其父帧(如果存在)。代理看起来像这样:

//tell the parent that we're functional
var data = '{ "action" : "Loaded" }';
if (parent && parent.frames && parent.frames[0] && parent.frames[0].content) {
    parent.frames[0].content.postMessage(data, '*');
}

window.addEventListener("message", function (e) {
    if (e.domain == undefined) {
        //do something
    }
}, false);

另一方面,我的页面会侦听该消息,并在收到该消息时设置变量以显示正确加载的代理。如果他们从未收到消息,则所有操作都假定代理不可用,并且UI会相应地做出反应以阻止用户操作。看起来像这样:

$(document).ready(function () {
    window.addEventListener("message", function (e) {
        var args = (e.data && (e.data.length > 0)) ? JSON.parse(e.data) : {};
        if (args.action) {
            if (args.action == 'Loaded') {
                if (typeof ProxyLoaded_success == 'function') {
                    ProxyLoaded_success(args);
                }
            } 
        }
    }, false);
});

var proxyLoaded = false;
function ProxyLoaded_success(args) {
    proxyLoaded = true;
}

function abc() {
    if(proxyLoaded == true) {
        //do something here
    } else {
        alert("proxy didn't load. call support");
    }
}