使用jQuery动态加载JavaScript类文件时如何避免执行延迟竞争条件?

时间:2012-04-16 15:00:22

标签: javascript jquery

我现在有大约六个JS类文件。我没有放入一堆标签,而是使用jQuery动态加载它们 - 按顺序 - 就像这样:

var classes = ["A","B","C"...];
blah.load = function(callback) {
    for (var i in classes) {
        console.log("Loading "+blah.RootURL+"/"+classes[i]+".js");
        $.ajax({
            async: true,
            url: blah.RootURL+"/"+classes[i]+".js",
            dataType: "script",
            error: function(jqxhr, status, error) {
                console.log("Unable to load "+classes[i]+": "+status+", "+error);
            },
            success: function(data, status, xhr) {
                if (window.tmpLoadCount) {
                    window.tmpLoadCount++;
                } else {
                    window.tmpLoadCount = 1;
                }

                if (window.tmpLoadCount == classes.length) {
                    console.log("Initializing...");
                    callback();
                }
            }
        });
    }
};

目前我正在使用多个脚本代码,因此我可以继续工作。我在jQuery方法中遇到的问题是,有时候,在重新加载时,先前的脚本似乎在加载下一个脚本之前没有执行(或完成执行),即使使用async: true也是如此。我的课程非常简短。我会看到脚本通过“加载”日志加载,但后来看到一个错误,如“无法加载B:A不是构造函数”(如果B继承自A),这告诉我A不完全在执行B.prototype=new A();行时加载。

我在网上发现了一个对此的引用,并建议添加一个setTimeout()调用以给引擎一些时间,并建议这只发生在jQuery的“成功”回调中处理内容时...不幸的是我我不确定如何确保在不使用成功回调的情况下以动态方式按顺序加载所有内容。

除了许多<script/>标签或缩小(这使调试更难)或需要更改课程外,是否有人建议如何彻底避免这种“竞争条件”?我当前的想法,我不喜欢,是让每个类文件中的最后一行将它的类名添加到全局静态属性,并让ajax调用使用间隔来检查该属性以确定它是否应该加载下一个文件...... bleh。

2 个答案:

答案 0 :(得分:3)

RequireJS实际上是针对这种情况而设计的。你应该认真考虑使用它。我个人认为this blog post by Aaron Hardy是一个更好,更简洁,更清晰的描述RequireJS是什么以及如何使用它比他们自己的文档中实际包含的内容。您可能需要几分钟时间来阅读它,我认为您会发现它是一个非常好的解决方案。

答案 1 :(得分:0)

在目前的情况下,你可以做的一件事就是只在现在完成时调用下一个脚本的加载。即在success函数中就像这样。

function something(i){
    $.ajax({
                async: true,
                url: blah.RootURL+"/"+classes[i]+".js",
                dataType: "script",
                error: function(jqxhr, status, error) {
                    console.log("Unable to load "+classes[i]+": "+status+", "+error);
                },
                success: function(data, status, xhr) {
                    if (window.tmpLoadCount) {
                        window.tmpLoadCount++;
                    } else {
                        window.tmpLoadCount = 1;
                    }
    something(window.tmpLoadCount);
                    if (window.tmpLoadCount == classes.length) {
                        console.log("Initializing...");
                        callback();
                    }
                }
            });
}