MDN's examples for Window.postMessage
include:
const popup = window.open(/* popup details */); // When the popup has fully loaded, if not blocked by a popup blocker: // This does nothing, assuming the window hasn't changed its location. popup.postMessage( "The user is 'bob' and the password is 'secret'", "https://secure.example.net" );
This is as I would have expected: that you need to wait for the target window to register its message
event handler before calling postMessage
. Unfortunately, I can't find a way to do that. (Maybe something with my_iframe.contentWindow.addEventListener
, if that's even possible?)
I did, however, find a comment suggesting you don't need to do that:
I don't think the event listener needs to be "ready". The messages should be saved until the event listener is added. – Barmar Feb 12, 2021 at 20:11
Which is it? Do we need to wait for the event handler to be registered, or don't we?
This is trivial to test.
const addMessageListener = () => {
addEventListener("message", (event) => {
console.log("Recieved: " + event.data);
});
}
const sendMessage = (message) => {
console.log("Sending: " + message);
postMessage(message, '*');
};
const wait = () => new Promise((resolve) => setTimeout(resolve, 500));
const actions = async () => {
sendMessage("Sent before adding listener");
await wait();
sendMessage("Sent IMMEDIATELY before adding listener");
addMessageListener();
sendMessage("Sent after adding listener");
}
actions();
Messages are not queued waiting for a listener to be added, but synchronous code might block a message (the Sent IMMEDIATELY one in this example) being sent until a listener is added which could give the illusion of such a queue. That isn't behaviour you should depend on.
that you need to wait for the target window to register its message event handler before calling postMessage. Unfortunately, I can't find a way to do that.
The approach I would take would be to add a message listener to the opener which, when it gets a suitable message, will start sending messages to the document in the new window. Then the document (whose URL you pass to window.open
) can send window.opener.postMessage("I am ready to accept your messages", origin)
once it has set up its own event listener.