有没有一种方法可以检测外部JS何时加载和执行?

6

有没有办法确定外部脚本何时已经加载并执行?我知道我们可以使用 onload 事件来确定它何时被加载,如下所示:

<script src=script.js async></script>
<script>
document.getElementsByTagName('script')[0].onload = function(){...}
</script>

那加载和执行呢?


你有理由相信 onload 事件可能在脚本解析之前触发吗?有参考资料吗?我并不希望出现这种情况(尽管一个简单的解决方法是设置一个计时器来标记从 onload 事件处理程序中的解析)。 - symcbean
如果我在onload事件之后使用它们(变量在外部脚本中),我会收到未定义变量错误。 - Core_dumped
3个回答

2
这里有一种使用jQuery延迟对象和$.ajax方法加载多个JS脚本的方法。当两个JS文件都被加载并执行时,控制台上会打印出消息。
演示请参见http://jsbin.com/qumojobawe/2/edit?html,js,output
var deferreds = [];

var jsFiles = ['https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-debug.js', 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/moment.js'];

$.each(jsFiles, function(idx, url) {
  deferreds.push(jQuery.ajax({
    type: "GET",
    url: url,
    dataType: "script",
    cache: true
  }));
});

deferreds.push($.Deferred(function(deferred) { $(deferred.resolve); }));

$.when.apply(this, deferreds).done(function() {
  console.log("KnockoutJS & MomentJs is loaded", ko, moment);
});

如果脚本加载了其他组件并且未立即初始化,您可以使用以下 wait() 方法,在指定的时间间隔内重新检查以等待满足某些条件。
var wait = function (condFunc, readyFunc, checkInterval) {
    var checkFunc = function () {
        if (condFunc()) {
            readyFunc();
        }
        else {
            setTimeout(checkFunc, checkInterval);
        }
    };
    checkFunc();
};

例如,以下代码将每隔10毫秒检查当前时间的秒数是否以零结尾,并在条件成立时执行函数:
wait(
function() { return new Date().getSeconds() % 10 == 0 }, 
function() { console.log("this will be called when time is 0, 10, 20, 30, etc seconds", new Date()); }, 
10);

示例 http://jsbin.com/fayenigixo/1/edit


1

0
您可以使用以下方法检查命名空间是否“已加载”:
var isNamespaceDefined = function(moduleName) {
    var fields = moduleName.split('.'), cur = window;

    for(var i=0; i<fields.length; i++){
        if(typeof cur[fields[i]] === "undefined") return false;
        cur = cur[fields[i]];
    }
    return true;
};

使用方法:isNamespaceDefined("my.module.function") 结合setTimeout来检查加载情况:
var doWhenReady = function(){
    if(isNamespaceDefined("my.function")){
        // redefining the function;
        var _myFunction = my.function;

        my.function = function(){

            // do things Before the call

            _myFunction.apply(null, arguments);

            // do things After the call

        };
    }
    else{
        setTimeout(doWhenReady , 100);
    }
}

一个简单的解决方案,但可以添加一些时间检查和错误回调。

我确实想知道是否有一种不需要setTimeout的解决方案。无论如何,谢谢。 - Core_dumped
如果您的JS文件中无法使用回调函数,则等待某些事件发生是唯一的方法。 - Hacketo
问题在于我想要执行的函数使用了一个变量,该变量仅在找到 Dom 中的元素后才设置。即使我在外部脚本中定义完函数后立即执行它,它也会抛出错误,指出变量(我在 20 行前设置为 document.getElem...)未定义。这就是为什么我需要确切地知道脚本何时被执行,不能依赖于超时,因为这样的变量有数十个,并检查每个变量是否已定义不是解决方案。 - Core_dumped
我进行了编辑,希望能够帮到您。您应该在帖子中提供更多关于您想要实现的内容的信息。 - Hacketo
@Hacketo 创建一个 Promise,等待脚本元素的 'load' 或 'error' 事件。一旦这两个事件中的任何一个被调用,就进行检查。有些错误会发出 'error' 事件,而其他错误即使您的脚本从未运行也会发出 'load' 事件。 - Mi G

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