动态加载JavaScript文件和加载完成事件

4

今天我一直在处理动态加载 JavaScript 代码(文件)。我使用的解决方案是:

function loadScript(scriptUrl) {
        var head = document.getElementsByTagName("head")[0];
        var script = document.createElement('script');
        script.id = 'uploadScript';
        script.type = 'text/javascript';
        script.src = scriptUrl;
        head.appendChild(script);
    }

问题在于我不知道如何确保脚本内容的执行时间。由于脚本包含类(JS类),我编写了一个通过setTimeout调用的函数,检查这些对象是否已定义。这种方法不够灵活,因为它不是自动的。那么,有没有办法加载这些脚本并可靠地通知它们何时被执行?


1
重复的https://dev59.com/007Sa4cB1Zd3GeqP5rGl#3125918。请参考该链接。 - tcooc
1
为什么不看一下现有的解决方案,比如LabJS?http://labjs.com/ - Pointy
没有冒犯的意思,但这似乎是一个糟糕的设计决策。 - Fosco
LabJs 在使用 jQuery 时出现了故障,我今天早上尝试过了... - gotch4
可能是script onload/onerror with IE(for lazy loading) problems的重复问题。 - Marcel Korpel
如果我没记错的话,脚本是在加载事件发生之前执行的。但您可以随时在onload内进行测试,例如 if ('jQuery' in window)。不过对此我没有IE方面知识。 - Marcel Korpel
3个回答

3
你可以使用jQuery的getScript方法,并传递一个回调函数。
$.getScript("test.js", function(){
   alert("Script loaded and executed.");
 });

请参见:jquery

额...不幸的是,这必须加载jQuery本身,呜呜呜 - gotch4
1
+1. 这样你就可以通过在回调函数中嵌套getScript调用来支持依赖项并按顺序加载它们。 - Fosco
你可以查看jQuery源代码,它可以很容易地使用纯JavaScript实现,参见:http://gist.github.com/538106 - tszming
请注意,根据jQuery文档目前的说明:_回调函数在脚本加载完成后被触发,但不一定被执行。_也就是说,它不能保证脚本的执行。 - Ankit

2
除了使用JS库之外,最简单的方法是进行XMLHttpRequest并评估返回值。当数据返回时,“onload”将被触发,“oninit”将在您评估之后立即触发。
编辑:如果您想对此进行排序,可以创建一个AssetLoader,该AssetLoader接受脚本数组,并且只有在获取和初始化前面的脚本后才会执行eval()。
编辑2:您还可以使用评论中引用的脚本.onload。 eval方法的优点在于您可以分离和控制脚本导入的加载和执行部分。
编辑3:这是一个示例。考虑一个名为foo.js的文件,其中包含以下内容:


function initScript (scriptString) {
    window.eval(scriptString);
}

function getScript (url, loadCallback, initCallback, callbackScope) {

    var req = new XMLHttpRequest();
    req.open('GET', url);

    req.onreadystatechange = function (e) {

        if (req.readyState == 4) {
            if (loadCallback) loadCallback.apply(callbackScope);
            initScript.call(null, req.responseText);
            if (initCallback) initCallback.apply(callbackScope);
        }

    }

    req.send();

}

function fooScriptLoaded () {
    alert('script loaded');
}

function fooScriptInitialized () {
    alert('script initialized');
    foo();
}

window.onload = function () {
    getScript('foo.js', fooScriptLoaded, fooScriptInitialized, null);
}


你将会看到警告信息 "脚本已加载","脚本已初始化",以及 "bar"。显然,在这里的XMLHttpRequest 的实现并不完整,你可以对任何想要执行脚本的范围进行各种操作,但这就是它的核心。

在 eval() 函数初始化脚本之后,你可以在其周围添加 try-catch 块来查看是否存在任何错误阻止脚本的初始化。 - sevenflow

-2
你可以使用一个计数器变量和一种回调函数:
var scriptsToLoad = 10;
var loadedScripts = 0;
//...
function increaseLoadCount() {
loadedScripts++;
if(loadedScripts == scriptsToLoad) {
alert("start here");
}
}

//script1-10.js
increaseLoadCount();

或许比设置超时时间更好一些。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接