我刚刚了解到一个关于在抛出错误时执行 Javascript 的重要事实。在我开始对此下结论之前,我最好验证一下我是否正确。
给定一个包含 2 个脚本的 HTML 页面:
<script src="script1.js" />
<script src="script2.js" />
脚本1:doSomething();
脚本2:doSomeOtherThing();
这有效地导致将单个脚本作为一个单元进行处理:doSomething();
doSomeOtherThing();
特别是,如果 doSomething
抛出错误,执行被破坏。 'script2' 永远不会被执行。这是我的 “第一课” - 人们可能会认为,因为它是一个单独包含的文件,所以它不受 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
更进一步,将所有脚本包装在
$(document).ready()
中可能是一个很好的架构决策。确保所有脚本都“排队”执行。在上面的第二个例子中,如果 script2.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 的出色回答仍然有助于深入了解执行堆栈等概念。这两个脚本中的每一个似乎都在单独的执行堆栈中执行。
最佳答案
您将它们作为一个脚本运行的第一个假设是不正确的。即使 Script1 抛出错误,Script2 仍会执行。对于一个简单的测试,实现以下文件结构:
-anyFolder
--test.html
--test.js
--test2.js
test.html 的内容:
<html>
<head>
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="test2.js"></script>
</head>
</html>
test.js 的内容:
console.log('test before');
throw('foo');
console.log('test after');
test2.js 的内容:
console.log('test 2');
打开 test.html 时的输出(在控制台中):
test before test.js:1
Uncaught foo test.js:2
test 2
从这个测试中,您可以看到即使 test.js 抛出错误,test2.js 仍然运行。但是,test.js 在遇到错误后停止执行。
关于如果前面的脚本失败,则执行或不执行 JavaScript 片段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13067354/