event loop: do not ask about the order
结论
- microtask macrotask 的顺序依赖于 host 实现,我们不应该去依赖其顺序来实现具体逻辑
- 讨论一个基于 host 的顺序问题犹如孔乙己讨论茴香的茴字有四种写法一样
背景
如果你面试前端,那你大概率对这个 issue 中的问题有所了解
这个问题不知从何时起成为了一个面试中常见的问题,各种文章解释也如雨后春笋出现,之前我也并没有深究过这个问题,但在群大佬的指导下我才发现:
这个问题,他或许并不合理
要回答这个问题,我们必须要抛开那些对顺序的讨论,回到一切的根本,最终的裁判,js 语言行为和表现的守望者,去探寻规范中对这种行为的真实定义
ECMA don’t care
首先需要表明的一个事实。
尽管这个问题常常被归类为 js 问题,其实不然。
如果我们仔细看看,这个问题中最核心的内容:
Promise.then
回调的microtask
是什么settimeout
的macrotask
是什么- 以及
event loop
对两者的调度,(顺序如何
然而如果我们去查找 ECMA,就会发现
- ECMA 并没有对 event loop 做定义,也不考虑 event loop, event loop 实际上是 ECMA 的 host (例如 html or node)所定义和调度
setTimeout
的属于 html 的 web api Timer 实现,同样不属于 ECMA 的规范范畴Promise.then
确实由 ECMA 所定义,但是- 在 ECMA 中没有
microtask
, 只有 job ,且 ECMA 明确指出 job 是一个抽象概念,其具体实现由 host 决定 - 目前规范中有且仅有 promise then 回调需要依赖 Job 实现,HostEnqueuePromiseJob
microtask
实际上同样是出现于 html spec 中,用来在 html 环境下的作为 HostEnqueuePromiseJob 的 host 实现规范- 只要能满足对 Jobs 约束的实现,ECMA 并不在意 host 使用
microtask
还是macrotask
,因为他对此无感知
- 在 ECMA 中没有
可以说几乎这个顺序问题归属的绝大多数细节 ECMA 都不感兴趣(不由它所定义)
Host is matter
因此,这个顺序问题的所有细节都交由 host 去定义去实现,在不同的的 host (如 node 、html)下不一样的行为,都可以被接受
而现实中 node.js 10 之前和 html 的表现就不一样,当然最终 nodejs 为了兼容 web 端的表现,在 node 11 之后修改了行为。
但那又是另一回事了。
结语
- 或许在有些 host 里并没有 microtask,setTimeout promise.then 同归一类
- 或许在有些 host 里 microtask 不值一提,setTimeout 优先级远高于它
- 或者在量子计算机 host 面前,两者天生就是并行触发,无所谓先后
在这个顺序问题中,不可知论者占领了上风
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.