为什么 setTimeout 的回调在文档解析后执行?



我遇到一些代码,使用setTimeout来确保在文档被解析后执行回调。

例如:

<!DOCTYPE html>
<html>
<head>
<script>
setTimeout(() => console.log(document.readyState));
</script>
</head>
<body>
<!-- lots of HTML to parse, which will take a long time -->
</body>
</html>

这里首先解析HTML,然后在控制台中登录complete的文档readyState。

我的猜测是解析出现在回调之前的调用堆栈或类似的东西,但我不明白这是如何工作的。我预计解析和回调之间会有一个竞争,以首先完成。

为什么回调在文档被解析后执行?

因为setTimeout本质上是一个异步操作。即使没有指定实际超时(默认为0),它也不会立即执行。它将该任务添加到"稍后要做的事情列表"中。当当前操作(在呈现页面时执行初始内联代码)完成时,事件循环将继续执行该列表中的下一个内容。

它不能抢占当前操作,只有阻塞操作可以做到这一点,因为它们实际上是当前操作的一部分。任何添加到事件循环中的内容都将在稍后处理。

作为题外话,这也是为什么像setTimeoutsetInterval这样的东西不是100%准确的。正如您的代码意外显示的那样,超时实际上长于0。您还可以将超时设置为1000,然后立即进行阻塞循环,需要几秒钟来处理。尽管有1秒计时器,事件循环在几秒阻塞操作完成之前无法完成该操作。

最新更新