微任务宏任务以及EventLoop详解

先总结下那些我们常用的api是宏任务,哪些是微任务。
宏任务
scripts 正常同步脚本
setTimeout 定时脚本
setInterval 定时循环执行
setImmediate node 常用 浏览器端兼容差
requestAnimationFrame 按照屏幕刷新频率执行一次的时间执行
I/O 数据读取,交互事件
UI rendering 页面渲染

微任务
Promise then catch finally promise回掉
process.nextTick node环境下的语法
MutationObserver dom变化检测事件监听

本文主要讨论浏览器宿主下的任务机制。

EventLoop 是什么?
js因为是单线程执行,如果有一个任务耽误很久,后面的任务就会被堵塞。这样对于用户体验的来说是大打折扣的,于是就有了同步脚本和异步脚本,同步的脚本在主线程中执行,异步脚本会放在任务队列等同步脚本执行完了再依次调用任务队列里的任务到主线程中执行。

EventLoop

如上图,主线程执行,遇到异步回调函数方法压入对应的任务队列中,并继续向下顺序执行,等主线程里的同步脚本都执行完,在将从任务队列中,按照先入先出(如果有定时的,按照定时的早晚)的顺序读取异步回调函数到主线程中执行。执行完后继续回到主线程执行,如此循环不停,称为eventloop。

微任务和宏任务执行的时机?
所以一次eventloop是从主线程的同步程序开始执行的,执行的时候所有的异步任务不管是宏任务还是微任务都会压入到对应的队列里。主线程的同步程序是一个同步的宏任务,当这个宏任务执行完后,准备进入宏任务队列中调用另一个异步宏任务的时候,主线程会检测是否存在可以执行的微任务。微任务是在下一个宏任务前执行的,如上图所示。
下面通过例子来直观感受:

setTimeout(() => {//A
  console.log(1);
}0)
Promise.resolve().then(function() {//B
  console.log(2);
})
console.log(3);

执行流程
1.主线程执行console.log(3),setTimeout 宏任务会被推在任务队列中等待主线程完成。
2.主线程执行完毕,会先去检查是否有可执行的微任务。如果有,先执行微任务,执行B函数
3.如果没有可执行的微任务或者微任务执行完了,到任务队列中调用可执行的宏任务,执行A函数

所有打印的最终顺序应该是 3,2,1

再看一个例子

setTimeout(() => {
  setTimeout(() => { //A
    console.log(1);
  }, 100)
},0)
Promise.resolve().then(function() {
  setTimeout(() => {//B
    console.log(2);
  }, 100)
})
setTimeout(function () {//C
  console.log(4)
}, 0)
console.log(3);

执行顺序
1.主线程执行,打印3
2.查看有无可执行的微任务,执行微任务promise,B函数压入任务队列
3.按顺序执行宏任务,导致A 和 C 回掉压入任务队列,此时队列顺序 CBA C因为是0秒,所以排在BA的前面,BA因为定时事件一致,所以按照执行的顺序排列。
5.新一轮eventloop,主线程没有可运行的,没有微任务,取队列中的任务。
所以最终打印出 3,4,2,1

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

森哥的歌

一杯咖啡半包烟,助我熬过那长夜

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值