JS事件循环
用简单的流程解释事件循环
在了解什么是事件循环之前我们应该需要先行了解javascript是一个单线程语言
和JavaScript的事件分类
;
JavaScript 是一个单线程语言
什么是单线程。举个例子:这就好像食堂打饭,需要排队,如果只有一个窗口可以进行打饭,那么就可以看作是单线程,如果有好多个窗口可以进行打饭,这就是多线程同理,javascript中的所有任务都只有一条线程在处理。
显然这种机制会造成很多问题,如果一个任务卡死,那么整个都不能运行了,
或者其中有一个任务执行的很慢,那么后面所有的任务都会延迟执行,所以 JS 有了两个任务分类[同步任务]和[异步任务]
JavaScript 的任务分类
接上文,javascript 中饿所有任务被分为同步任务和异步任务两大类
同步任务介绍:就是只要扫描到,就会马上执行的任务(优先于所有异步任务)
异步任务介绍:即使被扫描到,也不会立即执行,而是会被压入异步任务队列,等待主线程中的任务被执行完毕,再被召唤执行
常见的异步任务有如下几种
- Promise.then() --微任务
- async/await ---Promise 的语法糖 ---微任务
- setTimeOut() ---宏任务
- setInterval() ---宏任务
- .....
setTimeout(() => {
console.log("1");
}, 0);
console.log(2);
结果是 2 1 虽然定时器是 0 秒,但是 setTimeout 是一个异步任务,会等到所有同步任务执行完毕再去执行
宏任务和微任务
JavaScript 的异步任务分为宏任务和微任务,
在异步任务中,有些异步任务的执行周期较长,被列入宏任务队列,有些执行周期较短被列入为任务队列
两种任务在执行顺序上是不一样的,当有异步任务被压入任务队列时,JavaScript 会将这两种任务放入两个新的任务队列,会优先执行已经存在的微任务,在所有微任务执行完毕之后会执行一个宏任务,注意是一个宏任务,之后再去微任务队列检查是否有未执行的微任务,如果有则全部执行,再回到宏任务队列再执行一个宏任务,依次循环,这套流程被称作事件循环(event loop)

来一个例题
setTimeout(() => {
console.log("1");
}, 0); //异步任务 - 宏任务
console.log(2); //同步任务
Promise.resolve().then(() => {
console.log(3);
}); //异步任务 - 微任务
console.log(6); //同步任务
结果为 2 6 3 1
解析参考:
首先,同步任务必定优先于所有所有异步任务并按顺序执行。所以输出 2 6。
同步任务执行完毕后,还剩下一个宏任务和一个微任务。
微任务优先于宏任务执行,所以先输出 3 再输出 1
得答案:2 6 3 1
第二题

来一道难一点的
//第一个宏任务
setTimeout(() => {
console.log(1); //宏任务中的同步任务
Promise.resolve().then(() => {
console.log(7);
}); //宏任务中的微任务
}, 0); //异步任务 - 宏任务
console.log(2); //同步任务
Promise.resolve().then(() => {
console.log(3);
}); //异步任务 - 微任务
//第二个宏任务
setTimeout(() => {
console.log(8); //宏任务中的同步任务
setTimeout(() => {
console.log(5);
}, 0); //宏任务中的宏任务 第四个宏任务
}, 0);
//第三个宏任务
setTimeout(() => {
Promise.resolve().then(() => {
console.log(4);
}); //宏任务中的微任务
}, 0);
console.log(6); //同步任务
结果为 2 6 3 1 7 8 4 5
解析参考:
首先,同步任务必定优先于所有所有异步任务并按顺序执行。所以输出 2 6。
然后同一批次中剩下一个微任务和一个三个宏任务。
因为宏任务必定会在同一批次环境中的微任务全部执行完毕后再执行,所以场上当前批次中唯一一个微任务先执行。输出 3
还剩下三个宏任务。执行第一个宏任务,宏任务中有一个同步任务和一个异步任务。这里要注意两点。
统一批次宏任务中按顺序执行
一次只执行一个宏任务,然后同步任务当场执行。微任务压入队列。然后就要去检查有没有微任务,有则执行
所以,第一个宏任务执行的时候,产生了一个同步任务和一个微任务。需要注意,宏任务一次只执行一个。执行完之后发现同步任务当场执行(输出 1),然后查看微任务队列中有没有微任务可以执行。发现有,则执行微任务(输出 7)
然后,才开始执行第二个宏任务。执行第二个宏任务产生了一个同步任务,同步任务当场执行(输出 8),产生一个宏任务(宏任务压入红任务执行队列,也就是所有宏任务之后),按事件循环,再次检查是否存在未执行的微任务,发现没有,不执行。
然后执行第三个宏任务,第三个宏任务中产生一个微任务,按事件循环,再去寻找是否存在未执行的微任务,发现有,则执行(输出 4)
最后执行第四个宏任务(第二个宏任务产生的)。走一遍事件循环的流程,输出 5
事件循环每一次只执行一个宏任务
这个是非常重要的一点
