2012-09-28 7 views
9

Utknąłem w tej sprawie godzinami.Problemy z window.postMessage na Chrome

Mam a.html na http://example.com, który zawiera element iframe z src do b.html na http://subdomain.example.com. a.html ma kod JS do postMessage w elemencie iframe.

Kod dla postMessage jest prosta:

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

Ale w ten sposób, Chrome zgłasza błąd:

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

Próbowałem również:

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

ale nie szczęścia!

Jest to jedyny sposób to działa:

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

Ale słyszałem „*” nie jest dobry do użycia.

Brak problemów w Firefoksie.

+0

Aby wyjaśnić, w faktycznym kodzie, używasz prawdziwej strony internetowej? –

Odpowiedz

15

Wygląda na to, że może to być problem z tym, że element iframe podrzędnego nie jest ładowany w momencie wysyłania sygnału, dlatego iframe.src nie ma poprawnej wartości.

Zrobiłem kilka testów i dostałem taki sam błąd jak ty, ale kiedy owinąłem wywołanie postMessage w setTimeout i czekałem 100ms, wtedy nie było błędu, który mówi mi, że jest to stan wyścigu inicjalizacyjnego.

Oto jak I wdrożone czystsze rozwiązanie bez setTimeout:

nadrzędny:

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) 

dziecka:

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) 

Jest to proste rozwiązanie, w którym dziecko będzie sygnalizować każdemu że jest załadowany (przy użyciu "*", co jest w porządku, ponieważ nie jest wysyłany żaden poufny element). Rodzic nasłuchuje załadowanego zdarzenia i sprawdza, czy to dziecko jest interweniowane w tym, że to emituje.

Rodzic wysyła wiadomość do dziecka, które jest gotowe, aby je otrzymać. Kiedy dziecko otrzymuje wiadomość, umieszcza dane w postaci <h1> i dołącza je do ciała < >.

Testowałem to w Chrome z rzeczywistymi subdomenami i to rozwiązanie sprawdziło się u mnie.

+0

Pierwsze zdanie "Wygląda na to, że może to być problem z tym, że element iframe dziecka nie jest ładowany w momencie wysłania sygnału" to była wskazówka, której potrzebowałem, aby komunikacja w trybie iframe działała ... dzięki! – RamRaider

Powiązane problemy