Javascript 等待加载高延迟脚本时,在加载DOMContentLoaded之前忽略document.write

Javascript 等待加载高延迟脚本时,在加载DOMContentLoaded之前忽略document.write,javascript,firefox,google-chrome,domready,Javascript,Firefox,Google Chrome,Domready,我已经尝试了很多不同的方式来表达这个问题给谷歌等,但都不走运。甚至不确定这个问题的标题是否抓住了问题的细微差别。我会试着解释,然后展示这个实验。我希望有人能对发生的事情做出解释 给定: 在正文结尾之前,您有一个脚本(a),它通过编程将脚本元素(使用我首选的技术document.createElement)插入引用远程脚本(B)的文档中 远程脚本B执行任何内容的文档写入(例如“hello,world”) 在正文结尾之前和脚本A之后,您有一个脚本(C),该脚本引用远程脚本,加载该脚本需要一段时间(

我已经尝试了很多不同的方式来表达这个问题给谷歌等,但都不走运。甚至不确定这个问题的标题是否抓住了问题的细微差别。我会试着解释,然后展示这个实验。我希望有人能对发生的事情做出解释

给定:

  • 在正文结尾之前,您有一个脚本(a),它通过编程将脚本元素(使用我首选的技术document.createElement)插入引用远程脚本(B)的文档中
  • 远程脚本B执行任何内容的文档写入(例如“hello,world”)
  • 在正文结尾之前和脚本A之后,您有一个脚本(C),该脚本引用远程脚本,加载该脚本需要一段时间(例如1s)
将要发生的是A执行,将B插入文档并开始下载资源。当B下载时,由于延迟,C将执行并等待。在C等待时,下载并执行B;我们还没有击中目标;document.readyState仍在“加载”。忽略从B写入的document.write;狼吞虎咽,好像我们是后装的。C然后完成下载并执行

实验:

  • 资料来源:
  • 直接试用:
  • 瀑布:手动链接[cl.ly/423P2M1D0R0E0K370G]
  • 远程脚本:手动链接[thumblemonks.com/js/stackoverflow-script-b.js]
我正在使用Cuzillion创建延迟。如果您查看瀑布图像,还将看到console.log消息,它显示在DOM点击“interactive”readyState(即DOMContentLoaded)之前执行所有操作

我希望浏览器中的输出是:

TOP
hello, world
hello again, world
BOTTOM
我得到的输出是:

TOP
hello, world
BOTTOM
你会注意到在我的实验中,我在定义为A和C之间添加了另一个脚本;它表明,如果您动态添加包含document.write的文本(即非远程脚本)的脚本,则a'中的doc.write将起作用

另外,dummy.js和CSS文件来自JSFIDLE。他们不是罪魁祸首;我可以在任何地方重现这个问题

我知道的事情:

  • 如果用IMG替换C,则没有问题
  • 如果用IFRAME替换C,则没有问题
  • 如果将A移到C之后,则没有问题
现在:

也许有一个完全合理的理由。肯定有,因为我测试过的所有浏览器的行为方式都大致相同。我想知道的是为什么?欢迎提供任何解释、提示和/或提示。甚至像“它在规格中,邓比:)”这样的暗示,我的皮肤很厚;我能应付

免责声明:我讨厌这个文件。我的意图不是以任何方式支持或支持它的使用。然而,考虑到我工作的性质,我现在必须解决这个问题,这种奇怪的事情突然出现在我身上。因此,我希望避免“您不应该使用document.write”这样的评论,因为我已经相信:)

SEC7112:由于mime类型不匹配,来自的脚本被阻止


这是你的问题。脚本被传输为
text/plain
,这对于JavaScript来说不是有效的MIME类型。

HTML5不支持从异步加载的脚本写入,这正是因为它的快速性:您无法知道脚本将在加载DOMContentLoaded之前还是之后运行。请参阅和步骤2和步骤3。关键是,如果脚本在加载DOMContentLoaded的竞争中胜出,但如果它在竞争中失败,则将被忽略,这将非常奇怪,并将导致页面有时工作,有时不取决于网络条件。

谢谢,Kolink。不过,这只是浏览器的一个功能。在Chrome中,这会执行。我试图让每个人都能看到源代码,但是我已经把这个文件移到了我的一个服务器上,并更新了Fiddle。“你能再试一次吗?谢谢,”鲍里斯·兹巴奇说。伟大的指针。应该从这些规格开始。他们将在浏览webkit源代码时提供帮助。我还没有完成对所有条件的分解,但是为了回应您关于DOM应该做什么的断言,我问:为什么脚本A在脚本C之后移动时执行良好?只有在C之前,这才是一个问题。再说一次,我并不想让document.write工作,我更想知道这里发生了什么。所以,当C在A之前出现时,B(由A加载)实际上需要等待解析完成。这可以解释为什么在这种情况下会忽略破坏性写入。但我想我必须接受这样一个事实:浏览器将执行A(当它位于C之前时),知道解析尚未完成——但仍然将文档视为已关闭。我觉得比赛状态有点奇怪。@Gus我不认为在你的设置中改变a和C的顺序会影响任何事情。你能发布一个链接到一个a和C颠倒的版本吗?还有。document.write仍然无法工作(显然),但您会注意到我们现在进入了交互式readyState;而在前面的示例中,我们仍然处于“加载”状态。你的鼠标指针主要是为我解释的。谢谢。@SKing7插入点由解析器维护。特别是当它看到
时。看见对于非内联脚本,“挂起解析阻止脚本”位将在脚本准备运行时执行相同的操作(请参阅“否则”下的步骤6和8)。但这只适用于解析阻塞脚本,这意味着不使用异步或延迟的脚本。