[JS入门到进阶] setTimeout(cb,0)回调内再调用setTimeout(cb,0),两者执行相差多久?

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

这是我的专栏《前端入门到进阶》,跟HullQin学前端,入门到进阶!带你进大厂!

问题

setTimeout的回调内再调用setTimeout,两个回调函数执行相差多少毫秒?

换种问法,下面的代码,会输出什么?

let last = new Date().getTime();
function callback() {
  const now = new Date().getTime();
  console.log(now - last);
  last = now;
  setTimeout(callback, 0);
}
setTimeout(callback, 0);
复制代码

我的思考

在浏览器中,页面渲染和JS执行是互斥的,这两者也是耗时的大头。当页面渲染时,JS会阻塞。

而在NodeJS中,没有页面渲染过程。所以仅考虑JS执行即可。

这样分析下来,浏览器中的相差毫秒,应该比NodeJS中的相差毫秒更大。而且当浏览器正在执行大量渲染时,时间间隔应该会变得更大。

此外,如果JS中也有计算密集型任务,那么也会使这个间隔增大。

验证

分别在浏览器和NodeJS执行了这段代码,结果如下:

浏览器

image.png

Windows和Mac电脑执行结果都是类似这样的,差距不大,基本是4-6ms(静态页面,且无其它JS逻辑)。

扫描二维码关注公众号,回复: 14481064 查看本文章

但很奇怪的一点是:开头输出了4次0,后面再也没有0了。

NodeJS

image.png

NodeJS环境下,基本是0-2ms(没有其它JS逻辑了)。

真相

虽然我开头的分析看似有理,但并没有讲出真相。

尤其是无法解释Chrome浏览器开头输出的4个0。

HTML标准官方文档

真相在这里: HTML Standard - Timers,这是W3C官方定义的HTML5规范文档。

  1. If timeout is less than 0, then set timeout to 0.

  2. If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.

主要看第五点,如果嵌套层数超过5,并且timeout参数设置了小于4ms,那么就设置timeout为4ms。

这完美解释了,为什么开头浏览器就输出4个0,随后都是4-6了。

MDN文档

MDN的setTimeout文档 中,也有对此的描述。

这里贴2个MDN的图:

image.png

image.png

写在最后

我是HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,联系我,交个朋友),转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费无广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享:《教你做小游戏》《极致用户体验》

猜你喜欢

转载自juejin.im/post/7131762053403901988