Modernizr.load 回调在加载脚本之前执行



在我的javascript的某个时候,我有以下内容(使用Modernizr 2.6.2):

Modernizr.load([{
    load: '/path/file.js',
    complete: function () {
        //do stuff
    }
}]);

它大部分时间都运行良好,除了在 IE8 上,大约 1 次中有 3 次它先执行回调,然后加载脚本。我在回调上添加一个断点,并在文件.js中添加另一个断点。两个脚本都在执行,只是有时交换顺序。

我试图隔离并重现错误,但我不能。每次我在页面上只有此代码(使用完全相同的 Modernizr 文件)时,它都能正常工作。出于这个原因,我相信我的项目中的其他东西可能会干扰,但我不知道接下来沿着 js 的 10000(真的!)行看什么。有没有人经历过类似的事情,或者知道是什么会导致这种行为?

我不是在为这种特定情况寻找解决方法。这是我真正想保持原样的众多实例之一。

编辑 1 - 新信息:使用网络面板,我可以看到正在完成两个请求(这是预期的),但第一个请求始终返回空白。第二个请求显示正确的内容。当两个请求完成后执行回调时,这工作正常,但有时回调在第一个(空)和第二个请求之间执行。那是它崩溃的时候!

编辑 2 - 新信息:好的,我现在可以重现它了。为了100%确定我的假设,我必须深入了解javascript引擎,而我不知道,所以我可能大错特错,但这是我发现的:

请求文件 1.js 和文件 2.js。如果 file2 在引擎忙于执行 file1 的回调时完成加载,则 file2 执行将位于队列末尾的某个位置,这意味着在 file2 的回调之后。

尝试等待所有文件加载,然后再触发回调。扩展下面的模式以满足您的需求。

Modernizr.load([{
load: '/path/file.js',
complete: function () {
    filesLoaded++;
    checkStatus();
}
}]);
function checkStatus(){
  if(filesLoaded == 2){
    //do stuff
  }else{
    setTimeout(checkStatus, 100);
  }
}

在对这个主题做了一些研究之后,我认为这个问题可能比最初看起来更常见,但被忽视了,因为它依赖于上下文,并且有不同的描述方式:

现代化加载 [A, B] 似乎在 A 之前执行 B,这怎么可能?

YepNopeJS:在小JS文件完全加载之前触发回调

https://github.com/SlexAxton/yepnope.js/issues/195


在阅读了这篇关于IE上遇到的不一致的好文章(在yepnope页面上引用)后,我想出了一个修复程序,该修复程序已通过github发送给yepnope维护者:

http://github.com/SlexAxton/yepnope.js/pull/196

我不知道它是否会被接受,但它解决了我的问题。


由于编辑库可能并不总是一个好主意,因此我建议以下解决方法:

//instead of
complete:function(){
    doStuff()
}
//try
complete:function(){
    setTimeout(doStuff, 0);
}

最新更新