前端开发核心知识进阶 —— 宏任务和微任务
首先看一段关于Promise的代码
console.log('start here')
new Promise((resolve,reject) => {
console.log('first promise constructor')
resolve()
}).then(() => {
console.log('first promise then')
return new Promise((resolve,reject) => {
console.log('second promise')
resolve()
}).then(() => {
console.log('second promise then')
})
}).then(() => {
console.log('auther first promise then')
})
console.log('end here')
分析代码:
- 首先输出
start then
- 接下来执行
Promise
构造函数,同步代码,输出first promise constructor
,同时将第一处Promise
的then
方法完成处理逻辑放入任务队列 - 继续执行同步代码,输出
end here
- 同步代码全部执行完毕,然后执行任务队列的逻辑,输出
first promise then
和second promise
- 当在
then
方法中返回一个Promise
时,second promise then
的then
方法进入任务队列,由于主线程中没有其他任务,因此会执行then
方法,输出second promise then
- 最后输出
auther first promise then
分类
任务队列中的异步任务其实又分为宏任务、微任务,也就是说宏任务和微任务虽然都是异步任务,都在任务队列,但是他们在不同的队列中。
宏任务:
- setTimeout
- setInterval
- I/O
- 事件
- postMessage
- setImmediate(Node.js中的特性,浏览器端已经废除该API)
- requestAnimationFrame
- UI渲染
微任务:
- Promise.then
- MutationObserver
- process.nextTick(Node.js)
宏任务与微任务的优先级
console.log('start here')
const foo = () => (new Promise((resolve, reject) => {
console.log('first promise constructor')
let promise1 = new Promise((resolve,reject) => {
console.log('second promise constructor')
setTimeout(() => {
console.log('setTimeout here')
resolve()
},0)
resolve('promise1')
})
resolve('promise0')
promise1.then(arg => console.log(arg))
}))
foo().then(arg => {
console.log(arg)
})
console.log('end here')
宏任务队列:setTimeout
微任务队列:promise1.then,foo().then
输出结果:
“start here”
“first promise constructor”
“second promise constructor”
“end here”
“promise1”
“promise0”
“setTimeout here”
结论:
每次主线程执行栈为空的时候,引擎都会优先处理微任务队列,处理完后,再处理宏任务