Search code examples
javascripthtmldeferred-loading

When do HTML async scripts *finish* executing?


There is a lot of documentation about how async and defer affect the timing of the loading and the start of execution of external scripts, but I can't find anything that mentions when the script finishes executing.

For instance, suppose the external script defines functions one(), two(), three(), and four():

<head>
    …
    <script async="async" src="…"></script>
    …
</head>

<body>
    …
    <script> window.onload="one()" </script>
        …
    <script> two() </script>
</body>

<script> three() </script>

</html>

<script> four() </script>

The external script starts loading in parallel with the HTML, and then executes as soon as it's loaded.

I'm pretty sure that two() is unrealiable, as it could be undefined when it gets called, but I don't know about the others.

Are any of the functions guaranteed to be available when they are called?


Solution

  • It looks like they are all unreliable, except for the onload() invocation.

    This page:

    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Load script</title>
        <meta charset="UTF-8" />
        <script async="async" src="script.js"></script>
        <script> one() </script>
    </head>
    
    <body onload="two()">
        <p>Test</p>
        <script> three() </script>
    </body>
    
    <script> four() </script>
    
    </html>
    
    <script> five() </script>
    

    produces:

    error messages for 1, 3, 4, and 5, log entry for 2

    but everything works fine without the async:

    log entries for 1, 3, 4, 5, and 2

    I.e. you can be sure the async script has finished when the onload() happens, but not before that.

    So in general, for async script loading:

    • Nothing in the HTML can rely on the script's having been loaded.
    • Nothing in the script can rely on anything in the HTML having been loaded.

    That severely restricts the circumstances under which async scripts can be used.

    The async scripts must not do anything other than defining functions, etc. And those functions can't be used in the HTML until the processing has reached the onload stage.

    <tag onclick="external_function()"> ... </tag>       <!-- works -->
    
    <script> something = external_function() </script>   <!-- fails -->