浅谈宏任务和微任务

372 阅读2分钟

前言

什么是宏观任务,什么是微观任务?
`宏任务:宿主(浏览器)发起的任务我们可以称之为宏观任务(macrotask)
script、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)
微任务:引擎(js)自己发起的任务叫做微观任务(microtask)
promise async await `
js执行宏任务和微任务的联系:
`先执行宏任务再执行当前宏任务内的微任务(在此过程中将遇到的微宏任务依次推入到eventqueue,
先进入eventqueue的任务会被先执行),执行完当前宏任务内的所有微任务之后,再执行下一个宏任务,
以此循环,当然在微宏任务中同步任务会优先执行,而整体的scrpt标签就是第一个执行的宏任务`
tips:摘抄某位大佬话语
Promoise相关
`Promise中的异步体现在then和catch中,所以写在Promise中的代码是被当做同步任务立即执行的。
而在async/await中,在出现await出现之前,其中的代码也是立即执行的实际上await是一个让出线程的标志。
await后面的表达式会先执行一遍,将await后面的代码加入到microtask(微观任务)中`

示例(最近看到的经典题)

image.png

题解:
1.script是第一个宏任务

2.先执行当前宏观里的所有同步任务(主线程任务),再执行当前宏观里的所有微观任务,再执行下一个宏观任务,
即script宏(同->微)->下一个宏(同->微)->....

同步任务队列 console.log(4)-> async1()-> async2()-> console.log(8)

console.log(4); 同步任务 所以第一步打印4

async1(); 返回的是一个promise,promise本身是同步,所以 第二步打印1,并且将await之后的放到微观任务队列

async2(); 同步任务打印3promise();promise.then之前同步任务打印6,并将promise.then异步任务放到微观任务队列

console.log(8);同步任务打印8

微观任务队列 consol.log(2)-> console.log(7)

consol.log(2) 微观任务打印2

console.log(7) 微观任务打印7

宏观任务 setTimeout

setTimeoutfunction(){

console.log(5) 宏观任务打印5

})

打印顺序

同步4->同步1->同步3->同步6->同步8->微观2->微观7->宏观->5

图解:

image.png

其它案例(来小试牛刀一下吧)

题一:

async function async1() {
    console.log('async1 start')
    await async2()
    console.log('async1 end')
  }
  async function async2() {
    new Promise(resolve => {
        console.log('promise1')
        resolve()
      })
      .then(() => {
        console.log('promise2')
      })
  }
  console.log('script start')
  setTimeout(() => {
    console.log('setTimeout')
  }, 0);
  async1()
  new Promise(resolve => {
      console.log('promise3')
      resolve()
    })
    .then(() => {
      console.log('promise4')
    })
  console.log('script end')
  
题二:

Promise.resolve().then(()=>{
  console.log('Promise1')  
  setTimeout(()=>{
    console.log('setTimeout2')
  },0)
})
setTimeout(()=>{
  console.log('setTimeout1')
  Promise.resolve().then(()=>{
    console.log('Promise2')    
  })
},0)

题三:

async function async1() {
  console.log('async1 start')
  await async2()
  setTimeout(() => {
    console.log('setTimeout1')
  }, 0)
}
async function async2() {
  setTimeout(() => {
    console.log('setTimeout2')
  }, 0)
}
console.log('script start')
setTimeout(() => {
  console.log('setTimeout3')
}, 0);
async1()
new Promise(resolve => {
    console.log('promise1')
    resolve()
  })
  .then(() => {
    console.log('promise2')
  })

解答

1."script start"
  "async1 start"
  "promise1"
  "promise3"
  "script end"
  "promise2"
  "async1 end"
  "promise4"
  "setTimeout"
 2.
  "Promise1"
  "setTimeout1"
  "Promise2"
  "setTimeout2"
 3.
  "script start"
  "async1 start"
  "promise1"
  "script end"
  "promise2"
  "setTimeout3"
  "setTimeout2"
  "setTimeout1"