繁体   English   中英

DOMContentLoaded 事件和任务队列

[英]DOMContentLoaded event and task queue

听说有3个队列在Event Loop Processing Model有任务。

  1. MacroTaskQueue:这个队列有setTimeout、setInterval等回调函数
  2. MicroTaskQueue:这个队列有promise、mutationOberver..等回调函数
  3. AnimationFrameQueue:这个队列有requestAnimationFrame的回调函数。

所以,我想知道的是

  • 谁触发 DOMContentLoaded 事件?
  • DOMContentLoaded 的回调 function 在哪里排队? 宏任务队列还是微任务队列?
  • 最后,
var a = 10;
console.log(a);

setTimeout(function b() { console.log('im b'); }, 1000);

在这段代码中,

var a = 10;
console.log(a);

这段代码是否也在 MacroTaskQueue 或 MicroTaskQueue 中排队?

或者只有b在(分钟)1000 毫秒后在 MacroTaskQueue 中排队?

我在黑洞里。 请帮助我:D

你所说的“MacroTaskQueue”实际上是由几个任务队列组成的, 任务正在排队。 (请注意,规范仅使用多个任务源,实际上可能只有一个任务队列)。 事件循环处理开始时,浏览器将从哪个任务队列中选择下一个要执行的“主要”任务。 重要的是要理解这些任务可能根本不意味着任何 JavaScript 执行,JS 只是浏览器所做的一小部分。

在单个事件循环迭代期间,将多次访问和清空微任务队列。 例如,每次JS 调用堆栈被清空(即在几乎每次 JS 回调执行之后)并且如果还不够,则在事件循环处理 model中有固定的“执行微任务检查点”点。

虽然与队列类似,animation 帧回调实际上存储在有序的 map 中,而不是队列本身,这允许从这些回调之一“排队”新回调,而不会在之后立即出队。 更重要的是,很多其他回调也同时执行,例如滚动事件、调整大小事件、Web animation 步+事件、ResizeObserver 回调等。但是这个“更新渲染”步骤只是偶尔发生一次,通常以显示器刷新率。

但是,这并没有说明 DOMContentLoaded。

谁触发 DOMContentLoaded 事件?

此事件作为文档解析步骤的一部分在“结束”部分触发。 浏览器必须首先在 DOM 操作任务源上排队任务。 该任务最终将被浏览器选择为事件循环第一步的一部分。 一旦执行此任务的步骤,事件将被触发并在文档上分派。 这只是作为分派事件算法的一部分,浏览器将调用内部调用该事件算法,直到它 调用我们的侦听器的回调。
请注意,这个文档解析步骤本身作为一项任务非常有趣,因为这是最明显的地方,您将在“主”任务(例如每个 <script> )中交错多个微任务检查点。

DOMContentLoaded 的回调 function 在哪里排队?

回调 function 没有排队,它在概念上存储在 EventTarget 的事件监听器列表中 事实上,它存储在 memory 中,因为这里的 EventTarget 是一个 DOM object(文档),它可能附加到这个 DOM object,尽管这是一个实现细节,规范没有什么可说的,因为这对我们 web 是透明的-开发人员。

宏任务队列还是微任务队列?

我希望你现在能更好地理解,两者都不是。 任务队列和微任务队列只存储任务和微任务,不存储回调。 回调存储在别处,这取决于它们是什么类型的回调(例如,计时器和事件存储在不同的“概念”位置),然后某些任务或微任务的步骤将调用它们。

这段代码是否也在 MacroTaskQueue 或 MicroTaskQueue 中排队?

这取决于这个脚本是从哪里解析出来的。 如果它内嵌在经典的<script>标签中,那么这就是我们已经讨论过的特殊解析任务。 如果它来自<script src="url.js"> ,那么它将是从fetch a classic script排队的任务的一部分,但它也可以是微任务的一部分,例如,如果在模块脚本中await之后,或者如果你愿意,你甚至可以强迫它:

 queueMicrotask(() => { console.log("in microtask"); eval(document.querySelector("[type=myscript]").textContent); console.log("still in microtask"); }); console.log("in parsing task");
 <script type="myscript"> var a = 10; console.log(a); setTimeout(function b() { console.log('im b'); }, 1000); </script>

根据规范,从理论上讲,微任务甚至有可能成为“宏”任务,尽管显然没有浏览器确实实现了这一点。
综上所述,虽然我个人觉得所有这些东西都很吸引人,但作为网络开发者,你不应该在这上面阻止自己。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM