gremo
gremo

Reputation: 48439

Dynamically added script "onload": undefined global callback, which option do I have?

Step 1: I'm loading an external script, onload is set to call window.initControllers:

(function(document, tag) {
    var script = document.createElement(tag),
        el = document.getElementsByTagName(tag)[0];
    script.src = 'https://unpkg.com/@hotwired/[email protected]/dist/stimulus.umd.js';
    script.onload = function () {
        window.initControllers();
    };

    el.parentNode.insertBefore(script, el);
}(document, 'script'));

Step 2: actually define the window.initControllers function, in another dynamically added script:

(function(document, tag) {
    var script = document.createElement(tag),
        el = document.getElementsByTagName(tag)[0];
    script.type = 'module';
    var contents = "var initControllers = function () { console.log('initControllers'); };";
    contents += 'window.initControllers = initControllers;';

    script.appendChild(document.createTextNode(contents));

    el.parentNode.insertBefore(script, el);
}(document, 'script'));

The problem: on some page refresh, I get:

Uncaught TypeError: window.initControllers is not a function.

Apart from adding some fancy methods around setTimeout... which option do I have to ensure that window.initControllers is defined at the time that script step 1 is loaded?

Upvotes: 0

Views: 39

Answers (1)

C3roe
C3roe

Reputation: 96407

script.type = 'module' means processing of the script content will be deferred - so you could explicitly set defer for the first one.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#attr-defer:

Scripts with the defer attribute will execute in the order in which they appear in the document.

You might need to change the order that you append them in though, insertBefore will mean they end up in reverse order in the DOM.

Upvotes: 1

Related Questions