回到网络开发的早期阶段,我找到了一些民间智慧,对于像这样的代码
<script src=".../program1.js"></script>
<script src=".../program2.js"></script>
浏览器会暂停,加载javascript,编译,执行,继续下一步 script
标记,并重复。通过这种方式,浏览器将在页面上的所有javascript中运行并将其视为一个线性程序。
然而,在勇敢的新现代javascript世界中,我们通过它进行异步加载 async
属性
<script src=".../program1.js" async></script>
<script src=".../program2.js" async></script>
我的理解是这是一个 好事 因为现在浏览器不需要暂停,下载脚本并执行它。相反,它开始下载脚本,但将继续解析DOM。即等待javascript下载时网页不再阻塞。 (如果这不是真的,我会很感激修正)。
然而,更不清楚(并且更难测试)是这两个程序如何相互作用。它们似乎在相同的共享空间中运行(即,从用户角度来看,javascript仍然是单线程的,具有两个(全局,函数)范围)。但是,在我阅读的文档中,它们执行的顺序似乎不明确。
我已经阅读了MDN的文章 并发模型和事件循环。虽然有趣且有用,但它并没有完全回答我的问题。从我收集的内容,当浏览器加载时 program1.js
要么 program2.js
,javascript将向事件队列添加消息,并且当javascript引擎在事件循环中运行时将处理该消息。
对我来说缺少的是 - 这个消息说的是什么?是每个程序的单个消息,说“编译并执行所有这些javascript代码”?或者每个程序创建多个消息 - 在我看来可能看起来像
- 消息1:从该程序中提取所有函数并进行编译
- 消息2:从此程序中提取全局范围内的所有语句和表达式
- 消息3-n:将每个语句和表达式添加为单独的队列消息,以供以后处理。
当浏览器处于处理过程中会发生什么 program1.js
,但完成下载 program2.js
?是否可能交错执行每个程序的语句?
我意识到,作为客户端开发人员,这里的最佳实践是不依赖于全局范围并编写每个程序和函数,因此无论如何调用它都无关紧要,并且不会阻止其他人的代码。但是,我花了很多时间处理其他人的代码,其中一些代码表现不佳。我想了解幕后发生的事情,或者这是否是未定义的行为,与引擎无关,并且不会在实现之间排列。