Chrome上的window.postMessage问题

时间:2012-09-28 13:39:38

标签: javascript jquery html5 cross-domain postmessage

我被困在这几个小时。

我在http://example.com上有一个a.html,其中包含一个带有src的iframe b.html在http://subdomain.example.com上。 a.html有一些JS代码 将postMessage发送到iframe。

postMessage的代码很简单:

iframe_window.postMessage('message', iframe_element.src)

但是这样,Chrome就会抛出错误:

Unable to post message to http://subdomain.example.com. Recipient has origin null.

我也尝试过:

iframe_window.postMessage('message', 'http://subdomain.example.com')

但不要运气!

这是它的唯一方式:

iframe_window.postMessage('message', '*')

但我听说'*'不好用。

Firefox中没有问题。

2 个答案:

答案 0 :(得分:18)

看起来这可能是在发送信号时没有加载子iframe的问题,因此iframe.src没有正确的值。

我做了一些测试并得到了与你相同的错误,但当我在setTimeout中包装postMessage调用并等待100ms时,没有错误,这告诉我这是初始化竞争条件。

以下是我在没有setTimeout的情况下实现更清洁的解决方案的方法:

父:

window.addEventListener("DOMContentLoaded", function() {

    var iframe = document.querySelector("iframe")
      , _window = iframe.contentWindow

    window.addEventListener("message", function(e) {

        // wait for child to signal that it's loaded.
        if ( e.data === "loaded" && e.origin === iframe.src.split("/").splice(0, 3).join("/")) {

            // send the child a message.
            _window.postMessage("Test", iframe.src)
        }
    })

}, false)

子:

window.addEventListener("DOMContentLoaded", function() {

    // signal the parent that we're loaded.
    window.parent.postMessage("loaded", "*")

    // listen for messages from the parent.
    window.addEventListener("message", function(e) {

        var message = document.createElement("h1")

        message.innerHTML = e.data

        document.body.appendChild(message)

    }, false)

}, false)

这是一个简单的解决方案,在这个解决方案中,孩子会向任何人发出信号(使用“*”,这是好的,因为没有敏感信息被发送。)父母听取加载的事件并检查它是否是孩子它对发射它感兴趣。

父母然后向孩子发送一条消息,该消息已准备好接收它。当孩子得到消息时,它将数据放在< h1>中。并将其附加到< body>。

我在Chrome中使用实际子域进行了测试,此解决方案适用于我。

答案 1 :(得分:0)

更短的解决方案是将 postMessage 包裹在 iframe_element.onload 函数中。