0

I am using the following function to load scripts into a HTML file,

function addScript(src){
 var script = document.createElement('script');
 var location = "javascripts/";
 src =location + src;
 script.setAttribute('src', src);
 document.body.appendChild(script);
};

addScript('george.js');
addScript('fred.js');
addScript('main.js')

However, it seems to be able to load files which are too big (as in 200 lines). For example, if george.js has a class George, and the file is too long, attempts to create a new George() would fail.

I am convinced that it is a loading size problem because of the following:

1) new George would still fail if I comment out almost everything out from george.js.

2) new George would succeed if I delete any 10 functions from george.js.

3) new George would succeed if I split it up into 2 files

4). new Fred would fail if I add a lot of comments in fred.js.

5)To be clear, george.js can be

function George(){};

and I could call:

var george = new George();

in my file. However, if george.js becomes

function George(){};

/* 
(Insert hundreds of lines of comments here)
*/

the code

var george = new George();

will cause

ReferenceError: George is not defined

Why does this function have trouble loading a file of roughly 200 lines? And what can I do to deal with the problem?

Edit:

Attempt to try the window.setTimeout function.

AfterTimeout = function(){
  var george = new George();
}


window.setTimeout(AfterTimeout , 3000);

This does indeed seem to work.

I have ultimately made it work by setting script.async = false;.

  • does fred or george rely on accessing anything in the DOM? – derp Dec 19 '16 at 02:07
  • any errors in the developer tools console – Jaromanda X Dec 19 '16 at 02:18
  • Derp, I'm not sure of exactly what you mean by that. – Fluidized Pigeon Reactor Dec 19 '16 at 03:09
  • Also, no errors other than "The character encoding of the HTML document was not declared. " and "Reference Error: Fred is not defined" – Fluidized Pigeon Reactor Dec 19 '16 at 03:13
  • My guess is because loading in a JavaScript file takes time, you will want to use the functions only when that file has completely loaded. Try running this in a `setTimeout` of a few seconds and see if that's what's causing the issue. – Spencer Wieczorek Dec 19 '16 at 03:36
  • It does not work; in fact, the error seems to be found during "compile time", if that makes any sense. The error occurs immediately upon loading the page, even if I use window.setTimeout() – Fluidized Pigeon Reactor Dec 19 '16 at 04:10
  • Why are you loading your scripts this way? If you want to do this, then you have to wait for the `load` event on the script tag to fire before you do this. Instead of writing your own on-demand script loading logic, you are better off using some well-tested library or module. –  Dec 19 '16 at 04:15
  • Actually, it seems spencer wieczorek is right. Using the setTimeout function does work. – Fluidized Pigeon Reactor Dec 19 '16 at 04:31

3 Answers3

0

by creating DOM elements yourself and appending them to your document, you're attempting to load Javascript files asynchronously. if george.js finishes loading before var george = new George(); is called, then you got lucky this time and you won't have any problems. but if george.js is really big, or is being fetched over a slow network connection, then there's a good chance it won't be loaded and ready before you try to create a new George in your code.

the quickest way to load scripts, and to invoke a callback when the script is guaranteed to be loaded, is probably to use jQuery's getScript() function. the right way is probably to use something like webpack or browserify to properly identify and handle all dependencies between the different source files you write.

here is a pretty great answer discussing the details.

Community
  • 1
  • 1
Dan O
  • 6,022
  • 2
  • 32
  • 50
0

Its a bit hard to see what the error is without seeing the contents of fred or george but I can think of two things that might be causing your errors:

1) If you are accessing DOM elements (e.g. elements in the html), you will need to wait until the HTML elements have finished loading. You can do this by wrapping your code within a DOMContentLoaded callback

e.g

document.addEventListener("DOMContentLoaded", function() {
  function addScript(src){
    var script = document.createElement('script');
    var location = "javascripts/";
    src =location + src;
    script.setAttribute('src', src);
    document.body.appendChild(script);
  };

  addScript('george.js');
  addScript('fred.js');
  addScript('main.js')
});

2) The second thing you need to aware of is that if you dynamically add scripts like it might be async in nature. If you need the scripts to be sequentially called due to dependencies, you can try setting the async attribute to false

e.g.

script.setAttribute('async', false);
derp
  • 2,300
  • 13
  • 20
0

You must waiting script fully load to use its code. Catch event onload on script then execute. Use something like this:

var writeScripts = function (scripts, callback) {
    if(scripts.length==0) callback && callback();
    var src = scripts.shift();
    var s = document.createElement('script');
    s.type = "text/javascript";
    s.src = src;
    if(s.addEventListener) {
        s.addEventListener('load', function (e) { writeScripts(scripts, callback); }, false);
    } else if(s.attachEvent) {
        s.attachEvent('load', function (e) { writeScripts(scripts, callback); });
    }
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(s);
}
writeScripts(['george.js','fred.js', 'main.js'], function(){
    var george = new George();
});

This script load sequentially like browser, if you want it load parallel, just make a loop and add a count variable to handle.

takid1412
  • 296
  • 4
  • 8