如何处理异步加载库时的依赖关系

How to handle dependencies when libraries are loaded asynchronously?

本文关键字:依赖 关系 加载 异步 何处理 处理      更新时间:2023-09-26

Google pagspeed说我应该异步加载JS文件,但这给我的许多使用库和插件的页面带来了一个问题。

例如,我在一个页面上有以下代码:

$(document).ready(function () {
    var hound = new Bloodhound({ .......
});

因此,当页面加载时,我创建了一个Twitter Bloodhound(与Typeahead一起)对象。问题是,如果Bloodhound和Typeahead异步加载,则会抛出错误:

Uncaught ReferenceError: Bloodhound is not defined 

这是因为这些脚本还没有加载。

我想出了这个解决方案:

$(document).ready(function () {
    createBloodhound();
});

function createBloodhound() {
    if (typeof Bloodhound != "undefined") { // if bloodhound JS has loaded
        var hound = new Bloodhound({ .......
    }
    else {
        setTimeout(function(){
            createBloodhound();
        }, 10);
    }
}

这是一个好的做法,还是有更好的方法?

注意:我意识到有像RequireJS这样的库在加载文件时处理依赖关系,但我不认为这种类型的解决方案在我的情况下不起作用,因为我在包装文件中异步加载库(因为每个页面都需要它们)。这里的示例代码不会出现在每个页面上,而只会出现在我网站的特定页面上。

最好的方法是使用回调机制,您可以对它作出反应,而不是使用轮询机制。我使用了script.js,它简单而功能强大,并提供了回调机制。

如果没有这个,你可以自己实现一些东西。在性能方面,使用回调更好。

根据网站的复杂程度,不同的选择可能是最好的。如果…

  1. 你所有的javascript都在JS文件中
  2. 你的上面的内容在JS加载之前和之后看起来是一样的(或者足够接近相同的变化,当你的JS加载不会分散你的用户)
  3. 总文件大小很小(或者大多数JS都需要在每个人每次访问您的网站时都会访问的页面上)

…然后将它们合并到一个文件中,而不是单独的文件。这样就完全不用担心依赖关系了。将该脚本文件包含在body标签的底部(不需要async或defer属性,但如果需要,可以使用它们)。

如果你的一些javascript是必要的,使你的上面的内容看起来正确,做同样的事情,除了把你的JS分成两个文件。一个文件只包含使上面的内容看起来正确所必需的内容,而另一个文件包含其他所有内容。将第一个包含在head标签中(可能将其内联),并将第二个包含在body标签的底部。如果第二个依赖于第一个标签,则不要使用async属性,因为它可能首先被执行。

如果你有一些只在某些页面上使用的大JS文件,这些文件依赖于其他JS文件,把你的脚本放在你的body标签的底部,并使用defer属性。

如果你有javascript混合在你的HTML中,你可以使用回调机制(如script.js),或者你可以像Google Analytics那样建立执行队列,外部脚本知道寻找当它第一次加载