Why's THE Design(为什么这么设计) 是一系列关于计算机领域程序设计决策的文章(偏向于前端领域),在该系列会从不同的角度讨论这种设计的优缺点、对具体实现造成的影响。由 Draveness 的《为什么这么设计》 启发
正文
在前端技术圈子里面,对于 setTimeout
常常有一句结论,“setTimeout
的最小设置延迟是 4ms”。 按照 “某乎” 的方式,在回答一个问题之前得 “先看是不是”,“再看对不对或为什么”。
我们先来看第一个问题,“是不是存在具体的规范来指定了 4ms, 还是只是业界实践的既定事实?”
熟悉前端的知道,setTimeout
并不是由 ECMAScript 维护的,而是由 host environment 提供的,具体遵循的规范由 whatwg 来维护(至于为什么 ECMAScript 不直接提供 setTimeout 的功能,在 2011 年的 esdiscuss 中有了很多讨论,参与者有 Brendan Eich, kyle Simpson 等一帮前辈,后面会简单提到或另起一篇文章)。 回到 html standard,在 8.6 Timers-2020/6/23 中对于 setTimeout()
和 setInterval()
有详细的描述,我们只看其中的 10-13 行:
- If timeout is less than 0, then set timeout to 0.
- If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.
- Increment nesting level by one.
- Let task's timer nesting level be nesting level.
从上面的规范可以看出来:
- 如果设置的
timeout
小于 0,则设置为 0 - 如果嵌套的层级超过了 5 层,并且 timeout 小于 4ms,则设置 timeout 为 4ms。
到这里,我们似乎已经找到了 4ms 的出处,并且对于 setTimeout 的最小延迟有了更加精确的定义 - “需要同时满足嵌套层级超过 5 层,timeout 小于 4ms,才会设置 4ms”
有人可能会好奇,“什么是 timer nesting level 呢”?(我同样很好奇),具体看下面的代码(具体浏览器源码中是如何来实现 timer nesting level 和 最小时延的,后面会通过 chromium 源码解释):
setTimeout(() => {
setTimeout(() => {
setTimeout(() => {
setTimeout(() => {