js中的宏任务&微任务详解

首先我们从基础JS的执行机制去逐步开始理解...

1- JS是单线程语言 
2- JS的 Event Loop 是JS的执行机制。深入了解JS的执行,就等于深入了解JS里的 
event loop

JS为什么是单线程的???

场景描述:

现在有2个线程,process1 process2,由于是多线程的JS,所以他们对同一个dom,同时进行操作

process1 删除了该dom,而process2 编辑了该dom,同时下达2个矛盾的命令,浏览器究竟该如何执行呢?

 JS为什么需要异步???

场景描述:

如果JS中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。
对于用户而言,阻塞就意味着"卡死",这样就导致了很差的用户体验

JS单线程又是如何实现异步的呢???

console.log(1)
    
setTimeout(function(){
  console.log(3)
},0)

console.log(2)

//执行结果 1 2 3

也就是说,setTimeout里的函数并没有立即执行,而是延迟了一段时间,满足一定条件后,才去执行的,这类代码,我们叫异步代码。所以,这里我们首先知道了JS里的一种分类方式,就是将任务分为: 同步任务和异步任务

现在我们看看宏任务,微任务

宏任务{   settimeout 
    setInterval 
    I/O 事件 
    UI交付事件 
    postMessage 
    MessageChannel 
    setImmediate
    }

微任务{    Promise.then 
    Object.observe 
    MutaionObserver
    process.nextTick(Node.js 环境)
    }

执行流程图

1-首先执行script下的宏任务,

2-判断 js代码是同步 还是异步 

3-同步会进入到主线程 

4-异步加入到event table(事件表)

5-异步任务在event table中注册函数,当满足条件时,被推入 event queue(事件队列)

6-同步任务进入主线程的后会一直执行,直到主线程空闲时,

7-去任务队列中查看并以此执行的队列中的宏任务

接下来,我们通过经典的一个题目来加深一下理解

setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)

})

console.log(2)

来看看答案是否一致 :1,2,3,4

分析一下:

setTimeout就是作为宏任务来存在的,而Promise.then则是具有代表性的微任务,上述代码的执行顺序就是按照序号来输出的。

所有会进入的异步都是指的事件回调中的那部分代码
也就是说new Promise在实例化的过程中所执行的代码都是同步进行的then中注册的回调才是异步执行的。
在同步代码执行完成后才回去检查是否有异步任务完成,并执行对应的回调,而微任务又会在宏任务之前执行。

所以输出结果为1,2,3,4

看完上面的题我们再具体学习一下宏任务执行过程

  

流程图

-->1执行一个宏任务

-->2执行结束

-->3重点又来了 查看宏任务中是否有微任务(Event Loop)

生活实例:

在银行办理业务,每办理完一个业务,柜员就会问当前的客户,是否还有其他需要办理的业务。

(检查还有没有微任务需要处理)


而客户明确告知说没有事情以后,柜员就去查看后边还有没有等着办理业务的人。

(结束本次宏任务、检查还有没有宏任务需要处理)


这个检查的过程是持续进行的,每完成一个任务都会进行一次,而这样的操作就被称为Event Loop(这是个非常简易的描述了,实际上会复杂很多)

-->如果有则执行所有微任务--> UI render(页面渲染)

-->执行下一个宏任务

-->执行所有微任务

-->UI render-->......

中级练习 

setTimeout(_ => console.log(6), 5000)//创建宏任务
setTimeout(_ => console.log(4), 3000)//创建宏任务

new Promise(resolve => {            //创建一个微任务
  resolve()
  console.log(1)
}).then(_ => {  
  console.log(3)
  Promise.resolve().then(_ => {
    console.log('before timeout')
    setTimeout(() => {            //增加宏任务
      console.log(5);            
    }, 0);
    for (let i = 0; i < 90; i++) {//增加一个微任务
      if (i == 89) {
        console.log(7);
      }
    }
  }).then(_ => {                   //增加一个微任务
    Promise.resolve().then(_ => {  
      console.log('also before timeout')
    })
  })
})

console.log(2)

1,2,3,before timeout,7,also before timeout,5,4,6

setTimeout(_ => console.log(6), 5000)  :异步任务在event table中注册函数,当满足条件时,才会被推入 event queue(事件队列)

也是就说当5秒后才算是主线程空闲 才会将此条宏任务 推入事件队列 

就说到这里吧 相比大家都有所收获, 觉得满意可以给博主点赞奥 记得加关注,或者留言,欢迎赐教...

转载请注明 原文地址...js中的宏任务&微任务详解_Ben Meng的博客-CSDN博客_js微任务

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值