简体   繁体   中英

Loading scripts to page using javascript

I created some function that (should) load another files to my page (I'm making a library and I want to make all js files loadable in one line).

So that's part of HTML file:

<head>

    <title>Example</title>

    <script src="ENGINE/libs/jquery.js"></script>
    <script src="ENGINE/load.js"></script>

    <script src="EXAMPLE.js"></script>

</head>

And load.js:

function loadJSfromFile(src) {
    var h = document.getElementsByTagName('head').item(0);
    var s = document.createElement("script");
    //s.type = "text/javascript";
    s.src = src;
    h.appendChild(s);
};
loadJSfromFile("libs/canvasManager.js");
loadJSfromFile("libs/mainFunctions.js");
loadJSfromFile("libs/animations.js");
loadJSfromFile("libs/objects.js");
loadJSfromFile("libs/collisions.js");

The problem is: I receive errors, bacause another scripts on this site claim that functions from library are undefined. Does these files are loaded asynchronously? If yes, how to stop loading page until library will be loaded?

I use RequireJS and it is more helpful than you can even think of.

you can add it to your html page like:

<script data-main="scripts/main" src="scripts/require.js"></script>

and data-main attribute there is for your main.js . whenever you want to use a script or other external javascript libraries it would help you like:

//let's say you have util.js in the scripts folder
require(["scripts/util"], function(util) {

});

it has even fixed conflicts between different javascript libraries, it has a very great solution for jQuery and its AMD modules like:

require.config({
baseUrl: 'js/lib',
paths: {
    // the left side is the module ID, the right side is the path to
    //the jQuery file, relative to baseUrl. Also, the path should NOT include
    // the '.js' file extension. This example is using jQuery 1.9.0 located at
    // js/lib/jquery-1.9.0.js, relative to the HTML page.
        jquery: 'jquery-1.9.0'
    }
});

This is the code that I use to load a separate JS file at run time.

 function loadScript(url, success) {
    var script = document.createElement("script");
    script.src = url;
    var head = document.getElementsByTagName("head")[0],
            done = false;
    script.onload = script.onreadystatechange = function() {
       if (!done && (!this.readyState ||
               this.readyState === "loaded" ||
               this.readyState === "complete")) {
          done = true;
          if (success)
             success();
          script.onload = script.onreadystatechange = null;
          head.removeChild(script);
       }
    };
    head.appendChild(script);
 }

And then, to make sure that the script is loaded, I check for the function that I want to use with something like this:

 var myModule = (function(my) {
    my.doOperations = function(a, b) {
       var ret = {};
       ret.c = my.addNumbers(a, b);
       ret.d = my.difNumbers(a, b);

       if (myModule.hasOwnProperty("multNumbers")) {
          ret.e = my.multNumbers(a, b);
       }
       else {
          myModule.printToPage("Script not loaded yet")
       }
       return ret;
    };
    my.printToPage = function(textToPrint) {
       var newDiv = document.createElement("div");
       newDiv.innerHTML = textToPrint;
       document.getElementsByTagName("body")[0].appendChild(newDiv);
    };
    return my;
 }(myModule || {}));

I actually created a system that can assist with this. You an use it via a callback chain to load up some common libraries:

/* Initialize all external resources */
skitch.initLibs("jquery","js",function() {
    skitch.initLibs('bootstrap','js',function(){
        skitch.initLibs('bootstrap','css',function(){
            myCodeStart();
        });
    });
});
/* Begin Code */
function myCodeStart(){  
        alert("Everything's loaded!")
}

Here is code for the reusable system:

var skitch = {
    initLibs: function (t, n, r) {
        if (n == "js") {
            if (t == "$" || t == "jquery" || t == "jQuery") {
                var i = document.getElementsByTagName("head")[0];
                var s = document.createElement("script");
                s.type = "text/javascript";
                s.src = "http://code.jquery.com/jquery-latest.min.js";
                s.onreadystatechange = r;
                s.onload = r;
                i.appendChild(s);
                console.log("jquery js")
            }
            if (t == "bootstrap") {
                var i = document.getElementsByTagName("head")[0];
                var s = document.createElement("script");
                s.type = "text/javascript";
                s.src = "http://twitter.github.io/bootstrap/assets/js/bootstrap.min.js";
                s.onreadystatechange = r;
                s.onload = r;
                i.appendChild(s);
                console.log("bootstrap js")
            }
        } else if (n == "css") {
            if (t == "bootstrap") {
                var o = document;
                var u = "myCss";
                if (!o.getElementById(u)) {
                    var i = o.getElementsByTagName("head")[0];
                    var a = o.createElement("link");
                    a.id = u;
                    a.rel = "stylesheet";
                    a.type = "text/css";
                    a.href = "http://twitter.github.io/bootstrap/assets/css/bootstrap.css";
                    a.media = "all";
                    a.onreadystatechange = r;
                    a.onload = r;
                    i.appendChild(a);
                    console.log("bootstrap css")
                }
            }
        }
    }
}

This is not a full proof method all the time, and will require that inline scripts occur after everything is loaded. I suggest you look into RequireJS ( http://requirejs.org/ ) for a fully-fledged system.

Yes, the scripts are loaded asynchronously by default. I wrote a similar code to yours and faced the same problem. My code initially looked like this:

var scripts = [
  'http://' + window.location.host + '/jquery/jquery-1.11.2.min.js',
  'http://' + window.location.host + '/jquery-ui-1.11.4/jquery-ui.min.js',
  'http://' + window.location.host + '/d3/d3.min.js'
  'http://' + window.location.host + '/my/stuff.js'
];

var head = document.getElementsByTagName('head')[0];
for (i = 0; i < scripts.length; i++) {
  var newScript = document.createElement('script');
  newScript.type = 'text/javascript';
  newScript.src = scripts[i];
  head.appendChild(newScript);
}

What was happening was that the web page with the app had to be reloaded, because on the first attempt jQuery was loading too late for some reason and UI was broken due to missing dependencies, so basically the page was loading properly only every second time. The issue was gone after I disabled asynchronous loading of the JS scripts which can be simply done by setting the async property of the script to false:

var scripts = [
  'http://' + window.location.host + '/jquery/jquery-1.11.2.min.js',
  'http://' + window.location.host + '/jquery-ui-1.11.4/jquery-ui.min.js',
  'http://' + window.location.host + '/d3/d3.min.js'
  'http://' + window.location.host + '/my/stuff.js'
];

var head = document.getElementsByTagName('head')[0];
for (i = 0; i < scripts.length; i++) {
  var newScript = document.createElement('script');
  newScript.type = 'text/javascript';
  newScript.src = scripts[i];
  newScript.async = false;
  head.appendChild(newScript);
}

So in your case that should be:

function loadJSfromFile(src) {
    var h = document.getElementsByTagName('head').item(0);
    var s = document.createElement("script");
    //s.type = "text/javascript";
    s.src = src;
    s.async = false;
    h.appendChild(s);
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM