宏任务(macrotask )和微任务(microtask )
macrotask 和 microtask 表示异步任务的两种分类。
在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在 macrotask 的队列(这个队列也被叫做 task queue)中取出第一个任务,执行完毕后取出 microtask 队列中的所有任务顺序执行;之后再取 macrotask 任务,周而复始,直至两个队列的任务都取完。
宏任务和微任务之间的关系:
宏任务与微任务
下面的图会很清楚的告诉大家什么是宏任务及微任务:
一道经典的考察事件循环、宏任务、微任务的js题 :
async function async1(){
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
},0)
async1();
new Promise(function(resolve){
console.log('promise1')
resolve();
}).then(function(){
console.log('promise2')
})
console.log('script end')
第一步肯定是打印script start这不用说;
第二步执行到setTimeout时,它是一个宏任务,它会等当前宏任务全部执行完毕后再执行;
第三步执行到async1函数时,会先打印出async1 start,然后打印出async2,因为async定义的函数会立即执行,async2会返回一个promise的微任务进入回调队列线程;
第四步执行到new Promise时,会打印出promise1,同样resolve()会返回一个微任务进入回调队列线程;
第五步就打印出script end,到此时同步的都已经执行完毕,然后主线程会去回调队列线程拉任务;
第六步主线程拉到第一个任务是async2返回的一个promise,又会碰到一个resolve(),这时又将其推入回调队列线程;
第七步拉到new Promise的resolve(),这时会打印出promise2;
第八步就是打印出async1 end;
第九步就是当前宏任务执行完毕,执行下一个宏任务setTimeout,打印出setTimeout;