JavaScript中async属性脚本的执行线程及相关机制疑问
关于async属性脚本的线程执行与相关疑问解答
核心结论
所有JavaScript代码(包括带async属性的脚本)都运行在浏览器的主线程(也就是HTML解析器所在的同一个线程)中,只有脚本的下载过程是在后台独立线程完成的。
下面逐个解答你的疑问:
async脚本是否在独立线程执行?
否,async脚本的执行依然在主线程,只有下载阶段是后台并行的。若在独立线程,能否访问HTML解析器线程的数据?
因为实际是同主线程执行,所以可以访问DOM元素和文档元数据,但要注意:async脚本下载完成就会立即执行,此时页面可能还没完全解析,脚本位置后面的DOM元素大概率还没被创建,所以无法保证你要访问的元素一定存在。如果需要确保DOM就绪,可以在脚本里监听DOMContentLoaded事件。若同线程执行,解析器会被阻塞,那优化意义何在?
这里要拆分“下载”和“执行”两个阶段:
- 普通同步脚本:下载和执行都会阻塞HTML解析,页面完全卡住直到脚本处理完;
- async脚本:下载在后台线程,不影响解析,只有执行的时候会短暂抢占主线程,暂停解析,但执行完后解析会继续。
相比之下,async脚本的整体阻塞时间大幅缩短,页面能更快地呈现内容,优化效果依然明显。
- 若async等解析完再执行,那defer的意义是什么?
async和defer的核心差异在于执行时机和顺序:
- async:下载完成立即执行,不管HTML解析进度,多个async脚本的执行顺序由下载完成时间决定,完全无序;
- defer:下载同样在后台,但要等HTML完全解析完成后、
DOMContentLoaded事件触发前才执行,而且多个defer脚本会严格按照它们在HTML中的顺序执行。
所以defer适合有依赖关系、需要等待DOM全部解析完成的脚本(比如依赖其他库的业务脚本),而async适合独立无依赖、不需要等待DOM的脚本(比如统计脚本)。
内容的提问来源于stack exchange,提问作者Urooj
相关产品推荐
相关产品推荐

