动态加载 javascript 个文件时出错

error loading javascript files dynamically

我正在尝试在我的网页中延迟(动态)加载 javascript 个文件。

我用过这个:

http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml

   function loadjscssfile(filename, filetype){
    if (filetype=="js"){ //if filename is a external JavaScript file
        var fileref=document.createElement('script')
        fileref.setAttribute("type","text/javascript")
        fileref.setAttribute("src", filename)
    }
    else if (filetype=="css"){ //if filename is an external CSS file
        var fileref=document.createElement("link")
        fileref.setAttribute("rel", "stylesheet")
        fileref.setAttribute("type", "text/css")
        fileref.setAttribute("href", filename)
    }
    if (typeof fileref!="undefined")
        document.getElementsByTagName("head")[0].appendChild(fileref)
}

loadjscssfile("myscript1.js", "js") //dynamically load and add this .js file
loadjscssfile("myscript2.js", "js") //dynamically load and add this .js file
loadjscssfile("myscript3.js", "js") //dynamically load and add this .js file

这 3 个脚本将按顺序加载。

myscript3 依赖于 myscript2
并且 myscript2 依赖于 myscript1。

尝试以这种方式加载它的行为很奇怪。

看起来这些 未按预期的顺序加载 因此 有时会抛出未定义的错误,而 有时不会抛出任何错误

我是不是做错了什么。


已更新:

我正在使用此代码以正确的顺序加载文件

 function loadjscssfile(filename, filetype) {
        if (filetype == "js") { //if filename is a external JavaScript file
            var fileref = document.createElement('script')
            fileref.setAttribute("type", "text/javascript")
            fileref.setAttribute("src", filename)
        }
        else if (filetype == "css") { //if filename is an external CSS file
            var fileref = document.createElement("link")
            fileref.setAttribute("rel", "stylesheet")
            fileref.setAttribute("type", "text/css")
            fileref.setAttribute("href", filename)
        }
        return fileref;
    }

    function loadSync(files, types) {
        if (typeof (files[0]) === 'undefined') return false;
        var script = loadjscssfile(files[0], types[0]);
        script.onload = function () {
            files.shift();
            types.shift();
            loadSync(files, types);
        }
        if (typeof script != "undefined")
            document.getElementsByTagName("head")[0].appendChild(script)
    }

    loadSync(['scripts/module3.base.js', 'scripts/module3.core.js', 'scripts/module3.init.js'], ['js', 'js', 'js']);
    console.log('this should get printed when all the three files are loaded');


但是控制台输出是:

this should get printed when all the three files are loaded
scripts/module3.base.js:9 base is initialised
scripts/module3.core.js:6 core is initialised
scripts/module3.init.js:3 app is initialsed

看起来第一次调用 loadSync 本身就是一个异步调用

对于 HTML5 只需使用 async 属性( http://davidwalsh.name/html5-async 处的信息)

使用可选回调选项加载脚本的函数示例

function loadScript(url, callback) {
    if (!callback) callback = function () {};
    var script = document.createElement("script")
    script.type = "text/javascript";
    script.setAttribute("async", "true");

    if (script.readyState){  //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" ||
                    script.readyState == "complete"){
                script.onreadystatechange = null;
                callback();
            }
        };
    } else {  //Others
        script.onload = function(){
            callback();
        };
    }

    script.src = url;
    document.getElementsByTagName("head")[0].appendChild(script);
}

对于混合解决方案:

function loadjscssfile(url, type, callback) {
    if (!type) {
        type = "js";
    }
    var node;
    if (type === "js") {
        var node = document.createElement("script")
        node.setAttribute("async", "true");
        node.type = "text/javascript";

        if (node.readyState){  //IE
            node.onreadystatechange = function(){
                if (node.readyState == "loaded" ||
                        node.readyState == "complete"){
                    node.onreadystatechange = null;
                    callback();
                }
            };
        } else {  //Others
            node.onload = function(){
                callback();
            };
        }

        node.src = url;
    } else if (type === "css") {
        var node = document.createElement("link")
        node.type = "text/css";
        node.setAttribute("rel", "stylesheet");
        node.setAttribute("async", "true");

        if (node.readyState){  //IE
            node.onreadystatechange = function(){
                if (node.readyState == "loaded" ||
                        node.readyState == "complete"){
                    node.onreadystatechange = null;
                    callback();
                }
            };
        } else {  //Others
            node.onload = function(){
                callback();
            };
        }
        node.href = url;
    }
    if (node) {
        document.getElementsByTagName("head")[0].appendChild(node);
    } else {
        callback(new Error("File not found"));
    }
}

正在加载文件列表

function loadjscssfileList(arr_original, callback) {
    var arr = [];
    arr_original.forEach(function (v) {
        arr.push(v);
    });
    var next = function () {
        if (arr.length) {
            var file    = arr.shift();
            loadjscssfile(file[0], file[1], function () {
                next();
            });
        } else {
            callback();
        }
    };
    next();
};


// use without callback
loadjscssfileList([
    ["myscript.js","js"],
    ["style.css","css"],
    ["myscript2.js","js"]
]);

// use with callback
loadjscssfileList([
    ["myscript.js","js"],
    ["style.css","css"],
    ["myscript2.js","js"]
], function () {
    alert("loaded")
});

您可以同步加载它们。

function get_contents(file){
   var xhr = new XMLHttpRequest();
   xhr.open('get', file, false);
   xhr.send();
   return xhr.responseText;
 }

function loadjscssfile(filename, filetype){
var content = get_contents(filename);
if (filetype=="js"){ //if filename is a external JavaScript file
    var fileref=document.createElement('script');
    fileref.setAttribute("type","text/javascript");
    fileref.innerHTML = content;
}
else if (filetype=="css"){ //if filename is an external CSS file
    var fileref=document.createElement("link")
    fileref.setAttribute("rel", "stylesheet")
    fileref.setAttribute("type", "text/css")
    fileref.innerHTML = content;
}
if (typeof fileref!="undefined")
    document.getElementsByTagName("head")[0].appendChild(fileref)
}

外部加载:

有两种方法:

回调为另一个答案。

或者您可以这样做:

function loadjscssfile(filename, filetype){
    if (filetype=="js"){ //if filename is a external JavaScript file
        var fileref=document.createElement('script')
        fileref.setAttribute("type","text/javascript")
        fileref.setAttribute("src", filename)
    }
    else if (filetype=="css"){ //if filename is an external CSS file
        var fileref=document.createElement("link")
        fileref.setAttribute("rel", "stylesheet")
        fileref.setAttribute("type", "text/css")
        fileref.setAttribute("href", filename)
    }
    return fileref;
}

function loadSync(files,types){
    if(files[0] === 'undefined')return false; //if there's no files to load
    var script = loadjscssfile(files[0],types[0]); //load first file
    script.onload = function(){//after the script is loaded delete them and continue;
        files.shift();
        types.shift();
        loadSync(files,types);
    }
    if (typeof script !="undefined")
        document.getElementsByTagName("head")[0].appendChild(script)
}

loadSync(["myscript1.js","myscript2.js","myscript3.js"],['js','js','js']);

有开源的js可以解决你的问题。 您可以使用 LABJS or RequreJS 插件。

LABJSRequireJS 等脚本加载器将提高代码的速度和质量。

您可以像这样在 LABJS 中保留加载脚本的顺序。

$LAB.setOptions({AlwaysPreserveOrder:true})
.script("script1.js")
.script("script2.js")

$LAB
.script("script1.js").wait()
.script("script2.js")

script2.js 将等到 script1.js 加载完毕。

我想这会解决你的问题。