携手创作,共同成长!这是我参与「掘金日新计划 · 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执行了这段代码,结果如下:
浏览器
Windows和Mac电脑执行结果都是类似这样的,差距不大,基本是4-6ms(静态页面,且无其它JS逻辑)。
但很奇怪的一点是:开头输出了4次0,后面再也没有0了。
NodeJS
NodeJS环境下,基本是0-2ms(没有其它JS逻辑了)。
真相
虽然我开头的分析看似有理,但并没有讲出真相。
尤其是无法解释Chrome浏览器开头输出的4个0。
HTML标准官方文档
真相在这里: HTML Standard - Timers,这是W3C官方定义的HTML5规范文档。
If
timeout
is less than 0, then settimeout
to 0.If
nesting level
is greater than 5, andtimeout
is less than 4, then settimeout
to 4.
主要看第五点,如果嵌套层数超过5,并且timeout参数设置了小于4ms,那么就设置timeout为4ms。
这完美解释了,为什么开头浏览器就输出4个0,随后都是4-6了。
MDN文档
MDN的setTimeout文档 中,也有对此的描述。
这里贴2个MDN的图:
写在最后
我是HullQin,公众号线下聚会游戏的作者(欢迎关注公众号,联系我,交个朋友),转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费无广告。还独立开发了《合成大西瓜重制版》。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这2个专栏里分享:《教你做小游戏》、《极致用户体验》。