1、事件循环
大家都知道JavaScript是一门单线程语言
大白话讲一下吧:什么是单线程呢,就是主线程在执行代码时,只能从上往下一行一行执行,如果执行到某一行花费了很长时间,那么,呵呵,没办法,后面的代码只能等着,如果执行到某一行,代码出错了,呵呵,后面的也得不到执行。
但是,这样肯定不行的。所以JavaScript
引入了同步异步的概念,把比较耗时的代码放到异步API中执行,不要去阻塞主线程。也就有了**事件循环(Event Loop)**的概念
事件循环(Event Loop):先会执行栈中的内容,栈中内容执行后执行微任务,微任务清空后再执行宏任务,宏任务会在栈中执行,不停的循环. 如果还是不懂概念,参考这里
2、用三个框框解释Event Loop
不知道大家遇到过js
执行顺序的问题,什么样的组合都有,主要成员有以下几个
setTimeout
Promise
setImmediate
Process.nextTick()
每次打印出的结果都是不按套路出牌。今天,我们就用三个框框搞懂它们,请看大屏幕。
2-1、总体介绍
看图说话。图中一共三个框框,分别是红色(R)、绿色(G)、蓝色(B)。
执行顺序:先执行红框,再执行蓝框,最后执行绿框(辅助记忆:RGB)。 这里我们要记住执行顺序,以及每个框是用来干什么的。
2-2、红框
红框是调用栈,所有的代码必须在这里执行,当在这里执行代码时,如果产生了异步任务,那么就按照一定类别把该异步任务放到蓝框或者绿框里。绝对不能阻塞红框里的其他代码执行。
2-3、蓝框
蓝框里放的一个个任务叫microTask
,就是微任务的意思,当红框代码执行完毕后,红框就会从蓝框中取出一个任务并执行,在执行过程中如果产生了其他异步任务,那么继续放到蓝框或者绿框里。就这样,蓝框的一个个任务都被执行了。图中列举了几个属于microTask
任务的API
2-4、绿框
绿框里放的一个个任务叫macroTask
,就是宏任务的意思,当蓝框里的代码 执行完毕后,红框就会从绿框里取出一个任务并执行,在执行过程中如果产生了其他异步任务,那么继续放到蓝框或者绿框里。就这样,绿框的一个个任务都被执行了。图中列举了几个属于macroTask
任务的API
3、哪些是macroTask,哪些是 microTask
知道了每个框的作用以及总体的执行顺序后,该说一下,哪些API
属于microTask
(蓝框),哪些API
属于macroTask
(绿框)。
microtask
主要含:Promise
、process.nextTick
、MutaionObserver
maicrotask
主要含:setTimeout
、setInterval
、setImmediate
、I/O
、UI交互事件
以上列出的这些API
各自属于哪个任务必须要记住。
4、练习
说了那么多,来做几个练习吧。 先来个一年级的
setTimeout(() => {//放到了绿框里
console.log(2)
}, 0);
new Promise(function (resolve) { resolve() }).then(function () {
console.log(3)
})//放到了蓝框里
console.log(1)//默认在红框里,不动
以上代码的结果是1、3、2
解释一波吧:
- 这段代码首先整体作为一个宏任务(
macroTask
)进入到红框。 - 先遇到
setTimeout
,那么将其回调函数注册后分发到宏任务中,就是绿框里边。 - 然后遇到了
Promise
,then
函数分发微任务到微任务中,就是蓝框里。 - 遇到
console.log()
,立即执行。 - 到这里,整体代码作为第一个宏任务就执行结束了。接下来,该去蓝框看看了,发现有
then
,执行。 - 然后再到绿框里拿出
setTimeout
的注册回调函数,执行 - 结束。
再来一道复杂点儿的吧
console.log(1)
setTimeout(() => {
console.log(2);
process.nextTick(function () {
console.log(3);
})
}, 0);
process.nextTick(function () {
console.log(4)
})
new Promise(function (resolve) {
console.log(5);
resolve()
}).then(function () {
console.log(6)
})
以上代码执行结果为:1、5、4、6、2、3
分析过程留给大家吧,只要按照我们一开始说的,把所有的异步任务分门别类的放到对应的框框里,然后再按照RGB的顺序去执行,我相信,你能做对的。