【问题标题】:jQuery script execution order in html injectionhtml注入中的jQuery脚本执行顺序
【发布时间】:2014-01-31 16:00:46
【问题描述】:

考虑以下 JS 代码:

var html = '<script>$("body").append("a");</script>'
         + '<script src="script.js"></script>'
         + '<script>$("body").append("c");</script>';

$("body").append(html);

并假设 script.js 包含以下内容:

$("body").append("b");

似乎确实,“a”、“b”和“c”被附加到正文(按此顺序)。而且,显然,“c”仅在 script.js 完成加载后附加到正文(例如,如果 script.js 需要 5 秒完成加载,“c”将仅在 5 秒后附加到正文) .

我的问题如下:我们可以依赖 jQuery 中的这种行为吗?它是确定性的还是我们可能会遇到不可预知的情况?

这对于动态加载使用尚未加载的 .js 文件的脚本很有用。您可以假设 script.js 实际上包含function f(){},而第三行应该是&lt;script&gt;f()&lt;/script&gt;。如果脚本加载/执行的顺序始终相同,则不会有任何问题,否则您可能会遇到f is not defined 异常(如果在加载 script.js 文件之前执行了标记)。

【问题讨论】:

  • 您应该避免注入包含 &lt;script&gt; 元素的字符串,因为这不是脚本管理的合理架构方法。 jQuery 有一个 $.getScript() 方法,它明确地用于加载脚本,并利用 Promise 以便您可以轻松地链接脚本包含:$.getScript('foo.js').done(function () {$.getScript('bar.js')});
  • 管理脚本依赖关系的更好方法是依赖requirejs等工具。

标签: javascript jquery html asynchronous


【解决方案1】:

这不是 jQuery 特定的行为,而是浏览器的行为。加载文档中预定义的脚本时,它们会按顺序或外观加载。当您将脚本标记动态附加到文档时,情况并非如此。

如果您像显示的那样加载了 javascript 文件,它将在 DOM 设置元素的来源时开始下载外部文件。

示例:

Html 文件头中的脚本

$(function() {
    var html = '<script>$("body").append("a");<\/script>' +
               '<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"><\/script>' +
               '<script>$("#my-dialog").dialog();<\/script>';

    $("body").append(html);
}

Html 文件的正文元素

<div id="my-dialog">
    Some content here
</div>

上面的代码不会像你期望的那样执行。 a 将被附加到正文中,然后 jQuery.ui 被加载,最后会出现 dialog,但实际上第三个脚本会失败,因为 jQueryUI 尚未完成下载并且尚未解析。现在,如果您在控制台中输入$("#my-dialog").dialog();,则不会有任何问题,因为此时文件已下载并解析。

这是模块加载器流行的主要原因之一。您只需告诉它它需要什么,它就会按照需要的顺序为您加载它们。

您可以阅读更多关于脚本的 W3C 规范here

【讨论】:

  • 我知道模块加载器,但我也对能够使用
  • @Razvan 我会说,不包括第三方托管库,我无法使用“同步”方法让它乱序加载。我不会说这会一直发生。不过,它确实因timeout 而失败。就在那里,我强烈反对使用这种“模式”,因为如果你不小心,大多数使用回调的情况可能会导致它失败。
猜你喜欢
  • 2011-10-26
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多