Event-Loop、宏任务、微任务到底是个啥?

前言

众所周知,JavaScript是个单线程的脚本语言,通俗点说就是一般情况下,代码都是一行一行执行的,前期的CV工作中确实也是这么干的,后面随着接触了ajax请求、setTimeout、promise、async/await等等,随着而来的就是Event-Loop、宏任务、微任务这些概念,所以此次就针对这些概念做一个总结分享。

Event-Loop

Event-Loop即事件循环,是JavaScript为解决异步编程的一种机制。先看下同步代码的执行流程:

先上三行代码:

console.log('Hello World')

setTimeout(function fun1(){console.log('Timer1')},0)

console.log('你好')

结果: hello World 你好 Timer1

结果想必都毋庸置疑,但是为什么定时器设置了0秒,还是最后才被执行呢,接下来我们就探讨下。

以如下图所示类比JS引擎:

Brower:浏览器

call Stack:调用栈,所有JS代码都要先放到调用栈,才能被依次执行

webAPIs:可以理解为JS引擎中处理BOM、DOM节点、事件监听、回调函数等等的一种标准和规范。

callback Queue:顾名思义就是回调队列

Event-Loop:事件循环或者轮询,这里可以理解为同步回调队列与调用栈的一通信机制

在代码被编译执行的时候,是被一并送到调用栈中的,所以最初的调用栈是这样的:

接下来就是依次执行,先打印Hello World,调用栈遇到异步函数,发现它有一个回调函数fun1,此时将回调函数fun1,放到web APIs,等时间到达定时函数规定的时间,便把fun1推送到回调队列中(callback Queue),当call Stack中的同步代码执行完毕之后,call Stack 为空,再基于事件循环,也就是Event Loop机制,轮询callback Queue,发现有fun1,便再次推送到调用栈中,具体如下图所示:

又回到调用栈,按照同步代码依次执行的原理,再执行fun1,打印“Timer1”:

这也正好印证了,为什么即便是定时器设置了0秒,也是先执行两个同步的console.log函数,再执行定时器中的回调函数,也是Event Loop的作用所在。 总结一下:

1、同步代码一行一行放到调用栈

2、遇到异步任务,记录到web APIs中,等待时机

3、“时机”到了就推送到回调队列中

4、如果call Stack执行完毕,Event-Loop开始工作,轮询callback Queue,如果不为空,则将任务推送到call Stack中

5、然后Event-Loop继续轮询查找

DOM事件与Event-Loop

 console.log('1111')document.getElementById('btn').addEventListener('click', () => {console.log('2222')})console.log('3333') 

这里获取DOM节点,添加点击事件,也可以用Event-Loop解释,不同于setTimeout等函数,这里的回调什么时候被放到callback Queue,取决于什么时候触发点击事件。

macroTask 宏任务 与 microTask 微任务

先上代码:

 console.log('100')setTimeout(() => {console.log('200')})Promise.resolve().then(() => {console.log('300')})console.log('400') 

100和400的执行我们好理解,那200和300谁先执行呢?

先来一些概念:

宏任务:setTimeout、setInterval、Ajax、DOM事件

微任务:Promise async/await

ps:微任务执行时间要比比宏任务早

所以上述代码的打印顺序就是100、200、300、200

Evevt-Loop 与 DOM渲染的关系

前面说到了JS代码的执行顺序,那页面的DOM渲染又该什么时候执行呢,JS引擎是这么规定的,当call Stack(调用栈)第一次执行同步代码完毕,也就是Empty为空的时候,先去尝试进行DOM渲染,再去触发Event-Loop,再执行宏任务,因为Event-Loop类似一种循环机制,所以当宏任务在调用栈中执行完后,再去DOM渲染,Event-Loop再去查找,如此循环往复。 即每次调用栈为空,都是DOM渲染的机会,如果DOM结构有改变,再触发下一次的Event-Loop

当加入了Promise之后,也就是微任务之后,它与DOM渲染的顺序又是怎么样的呢?先说结果

同步代码>>微任务>>DOM渲染>>宏任务

这是因为,当执行到Promise时,它会根据执行“时机”放到microTask Queue中,也就是不会经过web APIs(web APIs是W3C规范,Promise(微任务)是ES6规范,不是W3C规范,宏任务是由浏览器规定的)

这也就是为何——微任务>>DOM渲染>>宏任务

那就先到这里吧,站在大佬的肩膀上产出的一篇文章,方便自己学习,如果能帮到他人,那就更好了。

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值