从代码开始分析,请观察以下代码
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的延迟是等价的,此时,谁的代码顺序靠前,谁就会再主线程空闲时优先被执行,