JS的事件循环和任务队列:
异步任务里面的微任务和宏任务:
https://zhuanlan.zhihu.com/p/364020645https://zhuanlan.zhihu.com/p/364020645
问题:
setTimeout(() => {
console.log(1);
}, 20);
setTimeout(() => {
console.log(2);
}, 0); //=>默认会有最小的等待时间(V8一般是5~6MS)
console.time('WHILE');
let i = 0;
while (i <= 99999999) {
i++;
}
console.timeEnd('WHILE');
setTimeout(() => {
console.log(3);
}, 10);
console.log(4);
运行结果:4 2 1 3
流程:
js引擎先从上到下执行代码,遇到1这个setTimeout后,交给定时器线程就不管了,然后继续执行到2这个setTimeout后也交给定时器线程不管了,继续执行到while循环,正常跑完,这里用时247ms,这个过程中前面的1和2的setTimeout由于设置的延迟时间是20和0(注释写了实际上并不是0,而是几ms)所以肯定是已经执行完了,所以就放到任务队列里面去了(2在前,1在后),js引擎继续执行到3的setTimeout继续交给定时器线程,最后执行到console.log(4) 就直接打印出来了,所以首先打印4,在js引擎执行完了所有的同步任务后,就回去异步任务队列里面找当前可以执行的任务,首先会执行2这个setTimeout的回调,所以打印2,这就是一个事件循环了,继续这么循环:先执行同步任务,由于这里没有同步任务了,所以继续去异步任务队列里面取下一个可执行的任务执行,然后打印1,以此类推,最后打印3,所以顺序就是 4, 2 1 3。
注意:
不是到定时器就放进任务队列,是定时器的时间结束了才把定时器里面的函数放进任务队列。
任务队列里面存放的就是一个一个回调函数,比如定时器的回调,点击事件的回调,请求事件的回调这些,这些回调函数就是等js引擎空了来执行的,js引擎会按照先来后到的顺序取出来执行。
如果循环执行时间小于10ms,先3后1,否则先1后3。