2012-09-28 41 views
9

Tôi đã bị mắc kẹt trong vấn đề này hàng giờ liền.Sự cố với window.postMessage trên Chrome

Tôi có a.html trên http://example.com chứa iframe có src đến b.html trên http://subdomain.example.com. a.html có một số mã JS để postMessage tới khung nội tuyến.

Mã để postMessage rất đơn giản:

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

Nhưng cách này, Chrome ném một lỗi:

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

Tôi cũng đã cố gắng:

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

nhưng may mắn không!

Đây là cách duy nhất hoạt động:

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

Nhưng tôi đã nghe '*' không tốt để sử dụng.

Không có sự cố trong Firefox.

+0

Chỉ cần làm rõ, trong mã thực tế của bạn, bạn có đang sử dụng trang web thực sự không? –

Trả lời

15

Dường như đây có thể là vấn đề với khung nội tuyến con không được tải tại thời điểm tín hiệu được gửi, do đó iframe.src không có giá trị phù hợp.

Tôi đã thực hiện một số thử nghiệm và gặp lỗi tương tự như bạn, nhưng khi tôi gói cuộc gọi postMessage trong setTimeout và đợi 100ms thì không có lỗi nào, cho tôi biết đây là điều kiện khởi tạo.

Đây là cách tôi thực hiện một giải pháp sạch hơn mà không setTimeout:

phụ huynh:

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) 

Child:

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) 

Đây là một giải pháp đơn giản, trong đó đứa trẻ sẽ là dấu hiệu cho bất cứ ai rằng nó được tải (sử dụng "*", đó là okay, bởi vì không có gì nhạy cảm đang được gửi đi.) Phụ huynh lắng nghe một sự kiện được nạp và kiểm tra xem đó là đứa trẻ đó là nội dung ested trong đó phát ra nó.

Sau đó, phụ huynh sẽ gửi một thông báo cho đứa trẻ, đã sẵn sàng nhận nó. Khi trẻ nhận được tin nhắn, nó sẽ đưa dữ liệu vào một số <h1> và gắn thêm vào số <body>.

Tôi đã thử nghiệm điều này trong Chrome với tên miền phụ thực tế và giải pháp này đã hiệu quả đối với tôi.

+0

Câu đầu tiên 'Có vẻ như đây có thể là vấn đề với iframe con không được tải tại thời điểm tín hiệu được gửi' là đầu mối tôi cần để có được giao tiếp iframe hoạt động ... cảm ơn! – RamRaider