2

I am having a weird issue that is rather difficult to recreate, but I will try to explain to the best of my abilities.

I have a setup.js which is a file that includes parameters for the scripts to be added to the document by the main script, like so:

{
    script1: true,
    script2: true,
    script3: false
}

I have a main script file, lets call it main.js which basically checks the setup file and then for every "true" does the following:

var element = document.createElement('script');
element.src = "path/to/file.js"
document.getElementsByTagName('body').appendChild(element);

Now I've checked using console.log, and the main.js file is the one that has to execute all the way to the end until any of the files added to the body begin loading, however they are then loaded one-by-one and should become ready for usage.

Now here comes the tricky part

I need to know when ALL of them are finished loading in order to be able to use their functions in the rest of the main.js file, so I need some sort of "onload" handler. I've tried to attach a addEventListener('load', function(){}) to the last element that was added, and it worked.

However.....

Once I changed the event listener function to something such as:

addEventListener('load' function(){
    script1Function(); //Which is defined in script1
    script2Function(); //Which is defined in script2
}

It started throwing errors such as "script1Function is not defined". I know that both scripts are loaded at this point, because I did a console.log("I have loaded") as the last line of each script, and those appeared in the console, but it is not possible to use the function definitions that were defined in these files.

What is even more.... if I instead do the following event handler:

addEventListener('load' function(){
    alert("Last script loaded"); //This line was ADDED
    script1Function(); //Which is defined in script1
    script2Function(); //Which is defined in script2
}

It all suddenly works. Adding "alert("whatever");" allows me to use the functions defined in the files.... I would assume it has something to do with "time needed for me to click "OK" on the alert dialog... but the entire thing doesn't make sense, because I know functions are defined by the time I am calling them.

3
  • Have you tried a while(typeof(script1Func) === "undefined") { if(typeof(script1Func) !== "undefined") { break; } } for script1, script2, scriptN? [Sorry for the horrible readability. On phone.] Commented Jun 2, 2016 at 18:27
  • I'd suggest adding a timeout to my above comment to prevent infinite loopage ;) Commented Jun 2, 2016 at 18:33
  • Hello, I could go that way, but, the issue I have is more conceptual, why are the functions not visible, that is the question Commented Jun 3, 2016 at 8:29

1 Answer 1

1
/*
    Example usage:
    importAsync(["script1.js", "script2.js", "script3.js"]);

    waitUntil(function() {
        return ((typeof(script1Function) !== "undefined")
                && (typeof(script2Function) !== "undefined")
                && (typeof(script3Function) !== "undefined"));
    });
 */
function waitUntil(testFunc) {
    var start = Date.now();
    var timeout = 3000;

    do {
        if((Date.now() - start) > timeout) {
            console.log("waitUntil() timed out");

            return false;
        }
    } while(!testFunc());
}

This is what I meant in the comments. I direct your attention to the example above the function:

importAsync(["script1.js", "script2.js", "script3.js"]);

waitUntil(function() {
    return ((typeof(script1Function) !== "undefined")
            && (typeof(script2Function) !== "undefined")
            && (typeof(script3Function) !== "undefined"));
});

importAsync is whatever function/method you have for loading the .js files - it's not relevant.

What is relevant, is waitUntil and the function you pass it. In the example above, I check whether functions from all three scripts exist (ergo: are not equal to undefined) and only then will execution of the script continue, due to the nature of the do..while loop. As I also mentioned in the comments, you're going to want a timeout on the do..while loop to prevent an infinite loop. You could add a parameter to waitUntil for the timeout as well if you'd like.

I hope this gives you a basic idea of what I meant in the comments and if you have any further questions, fire away!

Sign up to request clarification or add additional context in comments.

5 Comments

I will check if this suits my purpose, but I am mainly wondering why is this behavior happening, because I did make an "onload" handler that fires the function that is suppose to access them... so thye should be accessible, when the <script> element is loaded, yet they aren't. And to further make it more confusing, I console.log("Script1 finished loading"); at the very end of script1 and it was written in the console before an error was written that a function (which was defined in script1) was undefined.... weird stuff.
One of the major issues with this method is, there is a 'shit-ton' of functions in these files, and there is a lot of files + I am looking for dynamic loading here, so the waitUntil's parameter can be pretty hard to come to.
Have you tried adding an onload event to all of these elements, and in there for example have a simple i++. Then you could waitUntil(function() { i === scripts.length }); where scripts is the object/array which holds all these script1-N names?
I haven't though the script loading in the browser is a "blocking" sort of action, so only one is loaded at any time, so long as the last one is loaded, they will all be loaded, from what I understand. Though I have not tested it, might be worth a shot, will check it out.
It appears that the scripts added are not necessarily loaded in the order they are added with. Implementing a closure based i++ counter and limit check works. Fact remains it is weird though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.