为什么setTimeout会有4ms的延时

在阅读《React进阶实践指南》的调度与时间片章节时,作者提到setTimeout(fn,0)在循环调用时,最后的时间间隔会变成4ms左右,但作者没有详细解释,所以我上网查了资料,并且在这里记下来。

第一问:这是行业制定的标准 还是 Bug

在第一次看到setTimeout(fn,0)循环调用最后时间间隔为4ms时,我还认为这是一个bug,后来发现是自己想当然了。因为这是在HTML Standard (whatwg.org)里明确规定过的

image.png

如图上所示,HTML Standard里明确指出了使用setTimeout时,

  1. 如果设置的timeout小于0,则设置为0
  2. 如果嵌套的层级超过了 5 层,并且 timeout 小于 4ms,则设置 timeout 为 4ms

但其实各大浏览器厂商并没有完全按照这个标准实现,比如我在Edge浏览器(Chromium内核)下执行多个setTimeout命令,结果如下所示

image.png

可以看到1比0先执行。
这是因为Chromium源码里规定了在不满足嵌套层级时,timeout最小值限制为1ms,这就意味着setTimeout(()=>console.log(0),0) 相当于 setTimeout(()=>console.log(0),1);
这也是这个例子中1比0先打印的原因

第二问:为什么要制定这4ms的延时

因为浏览器本身也是基于event loop的,所以如果浏览器允许0ms,可能会导致一个很慢的js引擎不断被唤醒,从而引起event loop阻塞,对于用户来说就是网站无响应,这是让人很难接受的。

所以chrome 1.0 beta限制为1ms。但是后来发现1ms也会导致CPU spinning,计算机无法进入睡眠模式,经过多次实验后,Chorme团队选定了4ms,之后主流浏览器纷纷采用了这个4ms的设定。

参考文档
为什么 setTimeout 有最小时延 4ms ? - 知乎 (zhihu.com)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容