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.
Aby wyjaśnić, w faktycznym kodzie, używasz prawdziwej strony internetowej? –