我刚刚了解了一个关于在抛出错误时执行 Javascript 的重要事实。在我开始对此做出结论之前,我最好验证一下我是否正确。
给定一个包含 2 个脚本的 HTML 页面:
<script src="script1.js" />
<script src="script2.js" />
脚本1:
doSomething();
脚本2:
doSomeOtherThing();
这有效地导致单个脚本作为一个单元处理:
doSomething();
doSomeOtherThing();
特别是,如果doSomething
抛出错误,则执行会中断。'script2' 永远不会被执行。
这是我的“第 1 课” ——有人可能会认为,因为它是一个单独包含的文件,它不受 script1 的影响。但它是。 => 请参阅下面的“延迟更新”
现在,如果我们改变 script2 如下(假设我们在上面的某个地方包含了 jQuery):
$(document).ready({ doSomeOtherThing(); });
并将脚本放在 script2 之前:
<script src="script2.js" />
<script src="script1.js" />
执行顺序实际上仍然是“doSomething()”,然后(有时)是“doSomeOtherThing()”。
然而,它以两个“单元”执行:
doSomething
作为文档的 java 脚本的一部分提前执行doSomeOtherThing
在处理 document.ready 事件时执行。
如果doSomeOtherThing
抛出异常,它不会破坏第二个处理“单元”。
(我避免使用该术语thread
,因为我认为所有脚本通常由同一个线程执行,或者更准确地说,这可能取决于浏览器。)
所以,我的第 2 课:即使 JavaScript 错误可能会阻止任何后续脚本执行,它也不会停止事件循环。
结论 1
$(document).ready()
在定义应该独立于任何其他脚本成功执行的 JavaScript 代码块方面做得很好。
或者,换句话说:如果你有一段 JavaScript 并且想要确保即使其他脚本失败也能执行它,将它放在一个$(document).ready()
.
这对我来说是新的,因为如果脚本依赖于完全加载的文档,我只会使用该事件。
结论 2
更进一步,将所有脚本包装在 a中可能是一个很好的架构决策,$(document).ready()
以确保所有脚本都“排队”执行。在上面的第二个示例中,ifscript2.js
包含在 script1.js
示例 1 之后:
<script src="script1.js" />
<script src="script2.js" />
script1.js 中的错误doSomeOtherThing()
甚至会阻止注册,因为该$(document).ready()
函数不会被执行。
但是,如果 script1.js 也使用$(document).ready()
了 ,则不会发生这种情况:
$(document).ready(function() { doSomething(); });
$(document).ready(function() { doSomeOtherThing(); });
这两行都将被执行。然后稍后将执行事件循环,该循环会doSomething
中断,但doSomeOtherThing
不会受到影响。
这样做的另一个原因是渲染页面的线程可以尽快返回,并且可以使用事件循环来触发代码执行。
批评/问题:
- 我弄错了吗?
- 有什么原因需要立即执行一段代码,即不将其包装到事件中?
- 它会显着影响性能吗?
- 是否有另一种/更好的方法来实现相同而不是使用文档就绪事件?
- 如果所有脚本都只是将其代码注册为事件处理程序,是否可以定义脚本的执行顺序?事件处理程序是否按照它们注册的顺序执行?
期待任何有用的评论!
延迟更新:
就像 Briguy37 正确指出的那样,我的观察首先肯定是错误的。(“我是不是弄错了——是的!”)。以他的简单示例为例,我可以在所有主流浏览器甚至 IE8 中重现,即使 script1 抛出错误,也会执行 script2。
仍然@Marcello 的出色答案有助于深入了解执行堆栈等的概念。似乎这两个脚本中的每一个都在单独的执行堆栈中执行。