You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何setTimeout的回调会在文档解析完成后才执行?

为什么setTimeout回调会在文档解析完成后执行

你提到的代码示例如下:

<!DOCTYPE html>
<html>
<head>
  <script>
    setTimeout(() => console.log(document.readyState));
  </script>
</head>
<body>

<!-- 大量待解析的HTML内容,解析耗时较长 -->

</body>
</html>

要解释这个现象,核心要搞懂浏览器主线程的任务调度规则:

  • 浏览器的页面渲染、JS执行、HTML解析全部运行在主线程上,这是一个单线程,同一时间只能做一件事。
  • HTML解析属于主线程的同步优先级任务,只要解析没完成,主线程就会一直被占用,不会去执行其他异步任务。
  • setTimeout的回调属于宏任务,调用setTimeout的时候只是把回调函数注册到了宏任务队列,并不会立刻执行。哪怕延迟设为0,也必须等到当前主线程的所有同步任务全部执行完毕、主线程处于空闲状态时,才会从宏任务队列里取出回调执行。
  • 你预期的竞态不会出现,本质是因为HTML解析和setTimeout回调根本不是同一优先级的任务:同步的解析任务一定会先全部跑完,才会轮到异步的宏任务执行,所以回调执行时document.readyState必然已经是complete。

注意:这个写法属于非规范的黑盒hack,不推荐在生产环境使用。如果浏览器当前有其他高优先级同步任务阻塞了主线程,或者后续有其他更早注册的宏任务插队,也可能出现回调执行时文档还没解析完成的情况。正规的实现方式应该是监听DOMContentLoaded事件(DOM解析完成触发)或者load事件(所有资源加载完成触发)。

内容的提问来源于stack exchange,提问作者emccorson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 03:30:00