等待动态加载的脚本

Aar*_*lla 32 html javascript jquery load-order

在我的页面体中,我需要插入此代码作为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>
Run Code Online (Sandbox Code Playgroud)

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

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

Rob*_*Fox 37

在脚本文件中添加ID,以便查询.

<script id="hljs" async src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.0.0/highlight.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

然后在JavaScript中为它添加一个加载侦听器

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


jAn*_*ndy 31

这很安全.从历史上看,<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>
Run Code Online (Sandbox Code Playgroud)

但是,使用动态脚本标记插入而不是将其作为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);
Run Code Online (Sandbox Code Playgroud)

  • 如果指定了`async`和`defer`,现代浏览器只会异步执行脚本或延迟执行脚本.HTML中完全不需要`async = false`和`defer = false`.但是,默认情况下,动态创建的脚本将`async`设置为true,这就是在第二个代码示例中需要`scr.async = false;`的原因.见http://www.html5rocks.com/en/tutorials/speed/script-loading/ (16认同)
  • 使用`insertBefore`而不是`appendChild'是否有优势? (2认同)

Luk*_*son 16

const jsScript = document.createElement('script')
jsScript.src =
  'https://coolJavascript.js'

document.body.appendChild(jsScript)

jsScript.addEventListener('load', () => {
  doSomethingNow()
})
Run Code Online (Sandbox Code Playgroud)

动态添加脚本后才会加载

  • 在设置“加载”侦听器之前附加元素并不是最好的主意,因为如果加载太快(缓存),则将在附加侦听器之前调度“加载”事件。 (5认同)
  • @MarcosFernandezRamos - 您的意思是脚本应该附加在“加载”侦听器之后? (3认同)

Umu*_*acı 10

还有新功能jQuery 1.6.它被称为jQuery.holdReady().它实际上是自我解释的; 当你打电话时jQuery.holdReady(true),在你打电话ready之前不会解雇事件jQuery.holdReady(false).将此设置为false将不会自动触发就绪事件,它只是删除保留.

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

$.holdReady(true);
$.getScript("myplugin.js", function() {
     $.holdReady(false);
});
Run Code Online (Sandbox Code Playgroud)

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


Cir*_*四事件 9

等待多个脚本加载

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

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.

})();
Run Code Online (Sandbox Code Playgroud)

GitHub 上游:定义用法

在铬 75 中测试。


小智 5

这对我有用

function loadScript(sources, callBack) {
    var script      = document.createElement('script');
    script.src      = sources;
    script.async    = false; 
    document.body.appendChild(script); 
    
    script.addEventListener('load', () => {
        if(typeof callBack == "function") callBack(sources);
    });
}
Run Code Online (Sandbox Code Playgroud)