Search code examples
javascripthtmliframepostmessage

Race condition with addEventListener. When to bind?


I am using post message to adjust the height of an iframe dynamically. The html that is holding the iframe adds a listener that will trigger the frame resize. The (simplified) relevant code on the parent looks something like this:

<div id="dynamic_content">
    <iframe  src="http://my.content"></iframe>-->
</div>

<script>
    window.onload = function () {
        window.addEventListener("message", handleEventTrigger, false);
    };

    function handleEventTrigger(evt) {
        var height = evt.data;
        alert("Received: " + evt.data);
        if (isNumber(height)) {
            $("#dynamic_content").height(height + "px");
        }
    }

    function isNumber(str) {
        return !isNaN(str - 0);
    }    
</script>

On the source for the iframe I trigger a postMessage when it loads. Basically I have a div with id outerDiv which I want to send the height of. The relevant javascript code is:

window.onload = function () {
    var height = $("#outerDiv")[0].offsetHeight;
    if (isNumber(height)) {
        parent.postMessage(height, "*");   
    }        
};

My problem now is that this only works occasionally. I am assuming there is a race condition between adding the event listener and firing the post message. I rely on having bound the event listener before the post message is fired. What is the appropriate way to ensure this? Both are bound to window.onload. Are these addressing the same window, and is this a/the problem?


Solution

  • From what I understand the code is executed in the order it is printed, so I solved this by making sure the addEventListener is placed before the <iframe> in the code - and also stop doing this onload:

    <script>
        window.addEventListener("message", handleEventTrigger, false);        
        function handleEventTrigger(evt) { ... }
    </script>
    
    <iframe  src="http://my.content"></iframe>-->
    

    This solves the problem, and my race condition is gone. However, from what I've understood the recommendation is to place the js-code at the end of the html. If there is a good solution where I can achieve this too please shout out..