如何使用jQuery并行处理动态添加的脚本标签

6
这是我的情况:我通过动态添加了两个脚本:

$('body').append('<script src="http://localhost:8080/script_1.js"></script>');
$('body').append('<script src="http://localhost:8080/script_2.js"></script>');

然后我发现它们会按顺序而不是并行从Chrome控制台中加载。

然而,如果我使用本地JS,则可以并行加载它们。

document.body.appendChild(script);

或者jQuery函数:getScript
$.getScript('http://localhost:8080/script_1.js');

我搜索了很多资料,发现jQuery实际上会删除script标签,解析源代码,并使用其ajax函数$.ajax()来加载脚本,而不是让浏览器处理。但$.getScript()函数也使用$.ajax(),并且没有阻塞。显然,这不是$.ajax()的问题。
以下是一个测试案例: 转到http://jquery.com,并在控制台中粘贴以下脚本,它将通过jQuery两次添加js文件。
$('body').append('<script src="/jquery-wp-content/themes/jquery/js/plugins.js"></script>');
$('body').append('<script src="/jquery-wp-content/themes/jquery/js/plugins.js"></script>');

请检查时间线,您会发现它们是按顺序加载的。当然,我可以在上面使用本地js或$.getScript()来节省时间。

然而,我想知道为什么?为什么这些jQuery ajax调用从添加脚本标记不是并行的?

更新

更有趣的是,似乎这个顺序只适用于相同来源的脚本。我尝试从谷歌托管库加载一些js文件,它们是并行的。也尝试了以下内容:http://jquery.com

$('body').append('<script src="https://ajax.googleapis.com/ajax/libs/ext-core/3.1.0/ext-core.js"></script>');
$('body').append('<script src="https://ajax.googleapis.com/ajax/libs/ext-core/3.1.0/ext-core.js"></script>');

根据这篇文章,动态创建并添加到文档中的脚本默认是异步的。但它没有解释为什么jQuery附加的本地脚本不是这种情况。 - Moob
@Moob 是的,我知道...就像我提到的那样,我可以使用纯JavaScript document.body.appendChild(script); 进行加载,而且它们是并行的...但我只是想找出是什么秘密地使我的情况变成了顺序。 - Aobo Yang
规范 https://html.spec.whatwg.org/multipage/scripting.html#script 中有一些线索,但用他们的话说:“由于大多数历史原因,这些属性的确切处理细节有些复杂,涉及 HTML 的许多方面。因此,实现要求必须分散在规范中…” - Moob
1个回答

2

在将脚本附加到DOM时,根据跨域测试的不同,使用不同的ajax传输功能。

当协议:host:port不匹配时,发生跨域请求

在第一种情况下同源:

JQuery 使用 XMLHttpRequest open 函数,并强制使用 async=false 进行同步请求(查看源代码)。

xhr.open(
        options.type,
        options.url,
        options.async,
        options.username,
        options.password
    );

因此,控制台上会有警告(至少在Canary中)。

在主线程上同步使用XMLHttpRequest已被弃用

在第二种情况下跨域
JQuery使用ajax如下(查看源代码)。
script = jQuery("<script>").prop({
                    async: true,
                    charset: s.scriptCharset,
                    src: s.url
                }).....
document.head.appendChild(script[0]);

按照您所说的,这将并行加载。


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