等待动态加载的脚本

IT技术 javascript jquery html load-order
2021-03-14 09:04:10

在我的页面正文中,我需要插入此代码作为 AJAX 调用的结果:

    <p>Loading jQuery</p>
    <script type='text/javascript' src='scripts/jquery/core/jquery-1.4.4.js'></script>
    <p>Using jQuery</p>
    <script type='text/javascript'>
        $.ajax({
            ...
        });
    </script>

$.load()由于文档已加载,因此我无法使用,因此不会触发该事件。

这安全吗?如果没有,我如何确保在执行我的自定义生成的代码之前加载了 jquery 脚本。

6个回答

将 ID 添加到您的脚本文件,以便您可以查询它。

<script id="hljs" async src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js"></script>

然后在 JavaScript 中给它添加一个加载监听器

<script>
  var script = document.querySelector('#hljs');
  script.addEventListener('load', function() {
    hljs.initHighlightingOnLoad(); 
  });
</script>

这是相当安全的。从历史上看,<script>标签是完全阻塞的,因此<script>在前者完成解析/执行之前无法遇到第二个标签。唯一的问题可能是“现代”浏览器倾向于异步和延迟加载脚本。因此,为了确保顺序正确,请像这样使用它:

<p>Loading jQuery</p>
<script type='text/javascript' async=false defer=false src='scripts/jquery/core/jquery-1.4.4.js'></script>
<p>Using jQuery</p>
<script type='text/javascript'>
    $.ajax({
        ...
    });
</script>

但是,使用动态脚本标记插入而不是将其作为 HTML 字符串推送到 DOM 中可能是更好的主意。会是同一个故事

var scr  = document.createElement('script'),
    head = document.head || document.getElementsByTagName('head')[0];
    scr.src = 'scripts/jquery/core/jquery-1.4.4.js';
    scr.async = false; // optionally

head.insertBefore(scr, head.firstChild);
使用insertBefore而不是有优势appendChild吗?
2021-05-09 09:04:10
现代浏览器仅异步或延迟执行脚本,如果asyncdefer已指定。async=false并且defer=false在 HTML 中完全没有必要。但是,动态创建的脚本async默认设置为 true,这就是为什么您需要scr.async = false;在第二个代码示例中使用 。请参阅html5rocks.com/en/tutorials/speed/script-loading
2021-05-10 09:04:10
const jsScript = document.createElement('script')
jsScript.src =
  'https://coolJavascript.js'

document.body.appendChild(jsScript)

jsScript.addEventListener('load', () => {
  doSomethingNow()
})

动态添加脚本后才会加载

@Cansu,正是
2021-04-27 09:04:10
在设置 'load' 侦听器之前附加元素并不是最好的主意,因为如果它加载太快(缓存),则将在附加侦听器之前调度 'load' 事件。
2021-05-05 09:04:10
@MarcosFernandezRamos - 您的意思是脚本应该附加在“加载”侦听器之后吗?
2021-05-09 09:04:10

中还有一个新功能jQuery 1.6它被称为jQuery.holdReady()它实际上是不言自明的;当你打电话时jQuery.holdReady(true)ready事件不会被触发,直到你打电话jQuery.holdReady(false)将此设置为 false 不会自动触发就绪事件,它只会删除保留。

这是加载从文档中获取的脚本的非阻塞示例:

$.holdReady(true);
$.getScript("myplugin.js", function() {
     $.holdReady(false);
});

有关更多信息,请参阅http://api.jquery.com/jQuery.holdReady/

等待多个脚本加载

以下帮助程序仅加载多个脚本一次并返回一个Promise:

async function cirosantilli_load_scripts(script_urls) {
    function load(script_url) {
        return new Promise(function(resolve, reject) {
            if (cirosantilli_load_scripts.loaded.has(script_url)) {
                resolve();
            } else {
                var script = document.createElement('script');
                script.onload = resolve;
                script.src = script_url
                document.head.appendChild(script);
            }
        });
    }
    var promises = [];
    for (const script_url of script_urls) {
        promises.push(load(script_url));
    }
    await Promise.all(promises);
    for (const script_url of script_urls) {
        cirosantilli_load_scripts.loaded.add(script_url);
    }
}
cirosantilli_load_scripts.loaded = new Set();

(async () => {
    await cirosantilli_load_scripts([
        'https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js',
    ]);

    // Now do stuff with those scripts.

})();

GitHub 上游:定义用法

在铬 75 中测试。

不幸的是,它对我不起作用。我收到错误load_scripts is not defined
2021-04-26 09:04:10
现在工作完美。谢谢!
2021-05-11 09:04:10