簡體   English   中英

順序加載外部Javascript

[英]Loading external Javascript Sequentially

我正在研究一種依次加載其他外部JavaScript列表的JavaScript。

我到目前為止的代碼:

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");

我遇到的問題是,有時其他js文件會在Jquery文件完成其加載之前加載。 這給了我一些錯誤。

是否可以這樣做,以便僅在上一個文件完成加載后才啟動下一個JS文件。

提前致謝

確實有,但是圍繞此編寫了整個庫。 停止重新發明輪子,並使用已經起作用的東西。 嘗試yepnope.js,或者如果您正在使用Modernizr,那么它已經作為Modernizr.load

用技術術語來說:瀏覽器有一種有趣的方式來決定我執行/評估動態加載JS的順序,因此在經歷同樣的痛苦並檢查了很多文章,庫,插件等之后,我想到了這個解決方案,小巧,不需要jquery,對IE友好等。代碼被廣泛注釋:

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];
            }
        }
    }
}

當然,您也可以使用縮小版:

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])}};
loadJavascript("Jquery.js");
$(function(){
    $.getScript('second.js', function(data, textStatus){
        $.getScript('third.js', function(data, textStatus){
            console.log("loaded");
        });
    });
}

另外,考慮將Google或Microsoft CDN用於jQuery,這將節省您的帶寬,希望您的訪問者已經對其進行了緩存。

實際上,沒有必要在js函數中加載jquery。 但是,如果您堅持要求,則可以callback以確保在jquery之后加載其他js。

不過,我還是建議您在</body>之前加載jquery,然后使用$.getScript加載其他.js

您可以進行檢查以查看是否已加載jQuery,而不是最好的方法,但是如果您真的必須等到jQuery加載后再加載其他腳本,這就是我通過檢查$來做到的:

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");
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM