这几天重拾了一个以前遇到的面试题,联想起以前遇到的 “为什么 js的setTimeout 跟 css的transition 的时间对不上的问题”,又有了一些新的发现 。
友情提示:阅读本文需要了解 Macrotasks、Microtasks、Event Loop、执行栈。
传送门:https://zhuanlan.zhihu.com/p/33058983
定时器
定时器有两种,分别是 setInterval 和 setTimeout 。区别在于 setTimeout 只执行一次,而 setInterval 会一直循环执行。这里不详细讨论区别,只聊聊定时器的执行顺序。
DEMO 1
setTimeout(()=>{ console.log("1") }, 3000);console.log("2")// => 2// => 1
定时器回调函数的执行时间
上面的?,会在控制台先输出 2,然后在3秒之后会执行 setTimeout 的匿名回调函数,再输出 1。
setTimeout 是一个宏任务,它的回调函数会在执行栈中的所有任务执行完毕之后执行。
那么 setTimeout 是在何时开始计时的呢?
DEMO 2
console.log("1", Date.now())setTimeout(() => { console.log("2", Date.now()) }, 3000);let time = Date.now();let now = Date.now();while (now - time <= 3000) { now = Date.now(); }console.log("3", Date.now())setTimeout(() => { console.log("4", Date.now()) }, 2000);time = Date.now();now = Date.now();while (now - time <= 2000) { now = Date.now(); }console.log("5", Date.now())// => 1 1602514139821 // => 3 1602514142823// => 5 1602514144824// => 2 1602514144824// => 4 1602514144824
通过输出顺序可以看出,在执行到 setTimeout 的时候已经开始倒计时,由于 while 的耗时操作,导致输出 5 1602514144824 之后马上执行了两个定时器里面的回调函数。
在其他文章中有看到 定时器线程 这种说法,但是并没有找到具体的资料证实,不传瑶不信瑶
本意是不想写的过于复杂,因为涉及到一些其他的知识点,没看懂的话可以留言,下次改进一下