javascriptbrowserdeferred-executiondynamic-script-loading

Does this Funnelytics code contain a race condition?


I'm looking into tracking scripts that I've come across. Here's one by Funnelytics. At first look it seems like it has a bug:

(function(funnel) {
    var insert = document.getElementsByTagName('script')[0],
        script = document.createElement('script');
    script.addEventListener('load', function() {
        window.funnelytics.init(funnel, false);
    });
    script.src = 'https://cdn.funnelytics.io/track.js';
    script.type = 'text/javascript';
    script.async = true;
    insert.parentNode.insertBefore(script, insert);
})('8889dbc2-6c2f-5ba4-c201-dc8889dbc26c');

Isn't it possible that the function triggered by load will be called before the asynchronous script track.js gets executed? In which case, won't the line window.funnelytics.init fail, since window.funnelytics hasn't been defined yet?


Solution

  • This code does not contain a race condition. Notice that the event listener is attached to the script element, not the window object:

    script.AddEventListener('load', function() { // ...
    

    This function will only get called once the script loads and is executed.

    Even if the event listener had been attached to the window object, this code would still not contain a race condition. The function would only get called once all the window's subresources get loaded and executed, including any async scripts that are dynamically inserted, as happens here.