jQuery getScript 加载与执行

jQuery getScript load vs execution

提问人:Ben 提问时间:1/18/2014 更新时间:3/26/2020 访问量:6778

问:

getScript 文档对 success 回调是这样说的:

“脚本加载后会触发回调,但不一定执行。”

但在我的测试中,这似乎不是真的。对于具有以下功能的主机页面:

var startTime = new Date();

$.getScript("test.js")
 .done(function( script, textStatus ) {
    console.log( textStatus );
    console.log( "Done callback executing now.")
  })
  .fail(function( jqxhr, settings, exception ) {
    console.log("error." );
});

加载以下“test.js”脚本,该脚本将 UI 占用 5 秒钟:

console.log("ajaxed script starting to execute.");
var newTime = new Date();
while (newTime - startTime < 5000) {
    newTime = new Date();
}
console.log("elapsed time", newTime - startTime);
console.log("ajaxed script finished executing.");

在 FF 和 Chrome 中产生相同的可预测控制台输出:

ajaxed script starting to execute.
elapsed time 5000 
ajaxed script finished executing.
success
Done callback executing now. 

换言之,在加载并执行加载的脚本之前,成功回调永远不会触发。这似乎是因为在jQuery源代码中,globalEval函数立即调用脚本:

converters: {
    "text script": function( text ) {
        jQuery.globalEval( text );
        return text;
    }
}

那么文档是错的吗?如果它们是正确的,那么在什么特定情况下,在执行脚本之前会触发成功回调?

jQuery查询

评论

0赞 gnarf 1/18/2014
你能把你的问题和降价交给 github.com/jquery/api.jquery.com/issues 吗?:)
0赞 Julian Aubourg 1/18/2014
文档肯定是错误的,感谢您的提醒:)
1赞 Ben 1/21/2014
谢谢,github 问题已提交:github.com/jquery/api.jquery.com/issues/420
1赞 Zero3 9/17/2015
值得一提的是:我的一个应用程序正好受到这种竞争条件的影响。外部脚本除了设置全局变量外什么都不做,几乎总是在回调之前执行。但有时它不会,并且全局变量在回调运行时仍然存在,从而导致应用程序崩溃。我想知道是否有可靠的方法可以延迟回调的执行,直到脚本执行完毕......undefined

答:

0赞 gnarf 1/18/2014 #1

从我看源代码可以看出,我同意你的结论,即承诺应该总是在脚本执行解决。

但是,我的记忆告诉我,在jQuery 1.x支持的众多浏览器之一中注入标签有些奇怪。有问题的浏览器在脚本执行之前触发了加载的回调,否则我们不会在文档中添加有关它的注释。<script>(s|ed)

我很确定从那时起,它的实现已经发生了变化,文档中的问题行不再相关,无论哪种方式,我们都需要将问题摆在jQuery核心团队面前。你真的应该在 github 上提出一个问题 - 请随时抄送@gnarf。$.getScript

0赞 Otto G 3/28/2015 #2

这是原始发帖人对 GitHub 问题的回应中的一句话:

$.getScript("https://platform.twitter.com/widgets.js").done(..)对于某些 Twitter,媒体将触发完成的代码,而无需等待执行发生。

因此,文档似乎是正确的,尽管可能不像人们希望的那样具有描述性。

评论

0赞 Ben 4/2/2015
嗯......我想看看那个代码。我强烈怀疑 Twitter 小部件中有超时或某些异步行为。换句话说,脚本已经执行,任何后续的相关代码都在事件循环中发生。这意味着成功回调可能会在完成某些辅助操作之前触发。
0赞 Bizniztime 12/1/2015 #3

我在 jQuery 的 1.7.1 版本中遇到了这个问题。在 2.1.0 版本之前,上述函数使用间接调用 infamous 在全局环境中运行代码。$.globalEval()eval()

所以这在以前肯定是一个问题。

在版本 2.1.0 中,由于缺少某些间接 eval 调用,它们已切换到脚本插入。如果您愿意,可以在此处找到更多信息。

http://perfectionkills.com/global-eval-what-are-the-options/

在带有脚本插入的较新实现中,这一行正在发挥神奇的作用

context.head.appendChild( script ).parentNode.removeChild( script );

除非存在一些奇怪的底层浏览器机制,否则脚本似乎必须立即执行,然后才能从 DOM 树中删除。