开发者

Loading external Javascript Sequentially

I am working on a javascript that sequentially loads a list of开发者_Go百科 other external javascript.

The code I have so far:

function loadJavascript(url){
    var js = document.createElement("script");

    js.setAttribute("type", "text/javascript");
    js.setAttribute("src", url);

    if(typeof js!="undefined"){
        document.getElementsByTagName("head")[0].appendChild(js)
    }
}

loadJavascript("Jquery.js");
loadJavascript("second.js");
loadJavascript("third.js");

The problem I ran into is that sometimes the other js files loads before the Jquery file completes its loading. This gives me some errors.

Is it possible to make it so that the next JS file is only initiated when the previous file is finished loading.

Thanks in advance


Sure there is, but there's entire libraries written around doing this. Stop reinventing the wheel and use something that already works. Try out yepnope.js or if you're using Modernizr it's already available as Modernizr.load


loadJavascript("Jquery.js");
$(function(){
    $.getScript('second.js', function(data, textStatus){
        $.getScript('third.js', function(data, textStatus){
            console.log("loaded");
        });
    });
}

Also, consider using the Google or Microsoft CDN for the jQuery, it will save you bandwidth and hopefully your visitors will already have it cached.


Actually, it's not necessary to load jquery within a js function. But if you insist, you can callback to make sure other js loaded after jquery.

Still, I recommend you load jquery just before </body> then use $.getScript to load other .js


You could do a check to see if jQuery is loaded, not the best way to do it, but if you really have to wait until jQuery is loaded before loading the other scripts, this is how I would do it, by checking for $ :

loadJavascript("Jquery.js");    

T=0;
CheckIfLoaded();

function CheckIfLoaded() {
    if (typeof $ == 'undefined') {
      if (T <= 3000) {
          alert("jQuery not loaded within 3 sec");
      } else {
          T=T+200;
          setTimeout(CheckIfLoaded, 200);
    } else {
       loadJavascript("second.js");
       loadJavascript("third.js");
    }
}


In technical terms: Browsers have a funny way of deciding I which order to execute/eval dynamically loaded JS, so after suffering the same pain and checking a lot of posts, libraries, plugins, etc. I came up with this solution, self contained, small, no jquery needed, IE friendly, etc. The code is extensively commented:

lazyLoader = {
    load: function (scripts) {
        // The queue for the scripts to be loaded
        lazyLoader.queue = scripts;
        lazyLoader.pendingScripts = [];
        // There will always be a script in the document, at least this very same script... 
        // ...this script  will be used to identify available properties, thus assess correct way to proceed
        var firstScript = document.scripts[0];
        // We will loop thru the scripts on the queue
        for (i = 0; i < lazyLoader.queue.length; ++i) {
            // Evaluates if the async property is used by the browser
            if ('async' in firstScript ) {
                // Since src has to be defined after onreadystate change for IE, we organize all "element" steps together... 
                var element = document.createElement("script");
                element.type = "text/javascript"
                //... two more line of code than necessary but we add order and clarity
                // Define async as false, thus the scripts order will be respected
                element.async = false;
                element.src = lazyLoader.queue[i];
                document.head.appendChild(element);
            }
            // Somebody who hates developers invented IE, so we deal with it as follows:
            // ... In IE<11 script objects (and other objects) have a property called readyState...
            // ... check the script object has said property (readyState) ... 
            // ... if true, Bingo! We have and IE! 
            else if (firstScript.readyState) {
                // How it works: IE will load the script even if not injected to the DOM...
                // ... we create an event listener, we then inject the scripts in sequential order
                // Create an script element
                var element = document.createElement("script");
                element.type = "text/javascript"
                // Add the scripts from the queue to the pending list in order
                lazyLoader.pendingScripts.push(element)
                // Set an event listener for the script element 
                element.onreadystatechange = function() {
                    var pending;
                    // When the next script on the pending list has loaded proceed
                    if (lazyLoader.pendingScripts[0].readyState == "loaded" || lazyLoader.pendingScripts[0].readyState == "complete" ) {
                            // Remove the script we just loaded from the pending list
                            pending = lazyLoader.pendingScripts.shift()
                            // Clear the listener
                            element.onreadystatechange = null;
                            // Inject the script to the DOM, we don't use appendChild as it might break on IE
                            firstScript.parentNode.insertBefore(pending, firstScript);
                    }
                }
                // Once we have set the listener we set the script object's src
                element.src = lazyLoader.queue[i];
            }
        }
    }
}

Of course you can also use the minified version:

smallLoader={load:function(d){smallLoader.b=d;smallLoader.a=[];var b=document.scripts[0];for(i=0;i<smallLoader.b.length;++i)if("async"in b){var a=document.createElement("script");a.type="text/javascript";a.async=!1;a.src=smallLoader.b[i];document.head.appendChild(a)}else b.readyState&&(a=document.createElement("script"),a.type="text/javascript",smallLoader.a.push(a),a.onreadystatechange=function(){var c;if("loaded"==smallLoader.a[0].readyState||"complete"==smallLoader.a[0].readyState)c=smallLoader.a.shift(),
a.onreadystatechange=null,b.parentNode.insertBefore(c,b)},a.src=smallLoader.b[i])}};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜