JS宏任务和微任务结合实例分析

首先说一下执行顺序

微任务永远比宏任务先执行,当微任务中没有任务了才执行宏任务,中途如果微任务有加入任务,那么将停止宏任务,继续执行微任务

常见的宏任务队列

ajax,setTimeout,setInterval,DOM监听,UI Rendering等

常见的微任务队列

Promise的then回调,Mutation Observer ExtensionScriptApis,queueMicrotask等

下面通过2个经典面试题来总结

1.promise类型

序号1

  	setTimeout(() => {
	    console.log('set1')
	  new Promise(function(resolve){
	    resolve();
	  }).then(function(){
	    new Promise(function(resolve){
	      resolve()
	    }).then(function(){
	      console.log('then4')
	    })
	    console.log('then2')
	  })
	});

序号2

new Promise(function(resolve){
  console.log('pr1')
  resolve()
}).then(function(){
  console.log('then1')
})

序号3

setTimeout(() => {
 console.log('set2') 
});

序号4

console.log(2)

序号5

queueMicrotask(()=>{
  console.log('queueMicrotask')
})

序号6

new Promise(function(resolve){
  resolve()
}).then(function(){
  console.log('then3')
})

结合我上面所说的,从上往下看

1.

序号1,setTimeout是宏任务,不会立马执行,放入宏任务队列排队,排第一个

2.

序号2,console.log(‘pr1’)是在script中就会执行,所以第一个被执行,所以第一个打印的就是’pr1’,它的then回调是一个微任务,所以’then1’去微任务队列排队,排第一个

3.

序号3,setTimeout是宏任务,不会立马执行,放入宏任务队列排队,排第二个

4.

序号4,script中就会执行,所以第二个被打印,排在’pr1’后面

5.

序号5,queueMicrotask是一个微任务,所以去微任务队列里面排队,排在’then1’的后面,排第二位

6.

序号6,微任务,所以去微任务队列里面排队,排在’queueMicrotask’的后面,排第三位

7.

已有的微任务和script执行完毕,顺序如下

'pr1'
'2'
'then1'
'queueMicrotask'
'then3'

8.

序号1开始执行,首先打印’set1’,然后序号1里面有微任务,我们提到过的,只要有微任务被加进来,其他宏任务就会停止,会先打印前面的微任务,所以’then2’先被打印,然后再打印’then4’

9.

最后就打印’set2’

10.

最终顺序

'pr1'
'2'
'then1'
'queueMicrotask'
'then3'
'set1'
'then2'
'then4'
'set2'

2.async类型

序号1

async function async1 () {
  console.log('async1 start')
  await async2();
  console.log('async1 end')
}

序号2

async function async2 () {
  console.log('async2')
}

序号3

console.log('script start')

序号4

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

序号5

async1();

序号6

new Promise (function (resolve) {
  console.log('promise1')
  resolve();
}).then (function () {
  console.log('promise2')
})

序号7

console.log('script end')

结合我上面所说的,从上往下看

1.

前面2个函数,没有被调用,所以序号3先被打印

2.

序号4,setTimeout是宏任务,先进宏任务队列,排第一个

3.

序号5,调用了序号1的函数,所以script,'async1 start’被打印,接着调用了序号2的函数,然后’async2’被打印,序号1函数中的’async1 end’进行微任务队列,排第一个

4.

序号6,script中的’promise1’被打印,'promise2’进入微任务队列,排在
'async1 end’的后面

5.

'script end’被打印

6.

微任务队列依次打印,‘async1 end’,‘promise2’

7.

宏任务队列被打印’setTimeout’

8.

最终排序

'script start'
'async1 start'
'async2'
'promise1'
'script end'
'async1 end' 
'promise2'
'setTimeout'

应该写的还是比较详细的吧…

猜你喜欢

转载自blog.csdn.net/weixin_45389051/article/details/109368951