前端开发核心知识进阶 setTime相关考察
从代码开始分析,请观察以下代码
setTimeout(() => {
console.log('setTimeout block')
},100)
while(true){
}
console.log('end here')
执行以上代码不会得到任何的输出,这是因为,while(true){}
一直在循环,主线程被占用,无法运行下面的代码
setTimeout(() => {
while(true){
}
},0)
console.log('end here')
这段代码回打印end here
同步任务与异步任务
- 同步任务:当前主线程将要消化执行的任务,这些任务一起形成执行栈
- 异步任务:不进入主线程,而是进入任务队列,即不会马上执行的任务
当同步任务全被消化后,主线程空闲时,即上面提到的执行栈为空时,系统将会执行任务队列的任务,即异步任务
这样的机制保证了:虽然JavaScript是单线程的,但是对于一些耗时的任务,我们将其丢入任务队列中,这样就不会妨碍其他同步代码的执行,等到异步任务完成后,便会及进行相关的操作
定时器等待的时间与设置不符合
const t1 = new Date()
// 100ms的定时器
setTimeout(() => {
const t3 = new Date()
console.log('setTimeout block')
console.lo('t3-t1',t3-t1)
},100)
let t2 = new Date()
while(t2-t1 < 200){
t2 = new Date()
}
console.log('end here')
输出:
end here
setTimeout block
t3-t1,200
我们可以看到,虽然给定时器定的是100ms
,但是因为同步任务中的while
循环卡住。定时器只有在主线程的同步任务执行完后,才能执行,所以t3和t1的时间差为200ms
,为不是设定的100ms
最小延迟时间
setTimeout(() => {
console.log('100')
},100)
setTimeout(() => {
console.log('0')
},0)
输出;
0
100
因为代码执行时第二个setTimeout
的定时器函数将更快被触发,所以会先输出0
,再输出
100
但是将代码修改成一面的样子,情况就不一样了
setTimeout(() => {
console.log('1')
},1)
setTimeout(() => {
console.log('0')
},0)
输出:
1
0
这是因为1ms
与0ms
的延迟是等价的,此时,谁的代码顺序靠前,谁就会再主线程空闲时优先被执行,