1

I am trying to dynamically load a JavaScript file and, once it is loaded, run a function that is inside the file. In my main HTML, I basically have:

function load_javascript(js_file)
{
    function load_js_callback(example)
    {
        console.log("function " + function_in_js_file + " is " + typeof(function_name));
        if (typeof(function_in_js_file) == "undefined")
        {
            window.setTimeout(load_js_callback(example), 500);
            return false;
        }
        function_in_js_file(example);
    }

    var jstag = document.createElement("script");
    document.head.appendChild(jstag);

    // Browsers:
    jstag.onload=load_js_callback("example");
    // Internet Explorer:
    jstag.onreadystatechange = function() {
        if (this.readyState == 'complete') {
            load_js_callback("example");
        }
    }
    jstag.setAttribute('src',js_file);
}

load_javascript("/js/example.js");

From what I can find on the internet (https://stackoverflow.com/a/3248500 and https://stackoverflow.com/a/16231055) this should work, but the jstag.onload runs before the function_in_js_file is defined, so I need the window.setTimeout to check again until the function is defined.

Ideally, I would like to get rid of that timeout. Is there any way to know when the file has been completed loaded/parsed/executed (I'm not sure which is the right term) and the function is defined, ideally without changing the dynamic file? I have also tried putting the document.head.appendChild(jstag); after the jstag.setAttribute, but with the same results.

Jonathan
  • 6,507
  • 5
  • 37
  • 47
  • if you don't use a script require framework that does it for you, i know no js method to be sure your code has been executed. When i tried to do little custom solutions, i ended up with a var at the end of the file (for example named same as the file, or with prefix/suffix). I then test the existence of this var to assure all is executed – Kaddath Jul 05 '17 at 15:14
  • That would basically require a timeout like I have done if the var does not exist? – Jonathan Jul 05 '17 at 15:16
  • yes, or a setInterval rather. I should look at how browserify handles imports, and if there are checks like this.. i'm interested in the matter, i'll update if i find something – Kaddath Jul 05 '17 at 15:20

3 Answers3

2

The reason it's running before the script loads is because:

var jstag = document.createElement("script");
document.head.appendChild(jstag);

// Browsers:
jstag.onload=load_js_callback("example");

Is assigning the return value of load_js_callback to jstag.onload. The onload handler wants a function:

var jstag = document.createElement("script");
document.head.appendChild(jstag);

// Browsers:
jstag.onload=function() { load_js_callback("example"); };

As pointed out in the other comments, all this guarantees is that the browser has downloaded the script.

Adam Kewley
  • 1,224
  • 7
  • 16
  • This definitely looks like the answer, thank you for pointing that out about assigning the return value! However +Kaddath raises a question as to whether this will wait for the code to be executed, especially with larger files, or will run as soon as it is downloaded as you mention. I haven't found any documentation on this yet. – Jonathan Jul 05 '17 at 15:43
  • I'm going to mark this as the answer for now. Hopefully someone will come up with the answer we are looking for - do browsers wait for execution of an appended script before calling onload, but for now this seems to solve the problem. Thank you! :) – Jonathan Jul 20 '17 at 15:49
0

try this define a function called

function loadScript(sScriptSrc, oCallback) {
    var oHead = document.getElementsByTagName('head')[0];
    var oScript = document.createElement('script');
    oScript.type = 'text/javascript';
    oScript.src = sScriptSrc;
    // most browsers
    oScript.onload = oCallback;
    // IE 6 & 7
    oScript.onreadystatechange = function () {
        if (this.readyState == 'complete') {
            oCallback();
        }
    }
    oHead.appendChild(oScript);
}

and then call your script file and function inside it via callback

    loadScript("/js/example.js", function () {
                //call function
function_in_js_file(example);
            });
Lalit Sachdeva
  • 6,469
  • 2
  • 19
  • 25
  • you are doing nothing more than him, with this method, js is guaranteed to be loaded, but you cannot be sure that it has been executed – Kaddath Jul 05 '17 at 15:12
  • +Kaddath, thank you! That was what I was thinking. So the term I am looking for is executed ? – Jonathan Jul 05 '17 at 15:13
  • Have you tried the solution? Reason it will load and include the file at this time and anything written inside will be executed after including/loading/executing the fike. – Lalit Sachdeva Jul 05 '17 at 15:20
  • @LalitSachdeva i tried in the past already. This solution works perfectly with little files. But when the code imported is very long and you try to use things without waiting, things can get undefined. Note that this is valid mostly with dynamic imports. Usually, when the html page is parsed traditionnally, you don't have this problem – Kaddath Jul 05 '17 at 15:23
  • After reading +Adam Kewley's answer, I realise this is not exactly the same as mine since this is assigning a function to the onload and my code is actually assigning the output of my `load_js_callback` function, either `false` or `undefined`. So I'm still not sure whether onload will in fact wait until executed or not. – Jonathan Jul 05 '17 at 15:38
0

Consider using DOMContentLoaded js event

document.addEventListener('DOMContentLoader', function () {
    load_javascript("/js/example.js"); // Or what else you want to do
    // HERE I'm confident that my webpage is loaded and my js files too.
})
coockoo
  • 2,294
  • 17
  • 26
  • Thank you for the suggestion! Unfortunately, this does not answer the question because I was talking about dynamically adding scripts. – Jonathan Jul 05 '17 at 15:56