宏任务与微任务的区别
JavaScript采用单线程模型,通过 事件循环(Event Loop) 机制处理异步操作。
类比于厨师上菜的过程,顾客点的菜可能存在容易处理的 “软菜” 与难处理的 “硬菜” ,以及要加米饭酒水这些立马可以上的 “快菜”
这里立马可以上的快菜就是JS执行栈中的同步代码,更容易处理的软菜就是微任务队列中代码,最难处理的硬菜就是宏任务队列中的代码。
一、核心概念解析
1.1 宏任务(MacroTask)
典型场景:
- setTimeout/setInterval
- DOM事件回调
- I/O操作(如文件读写)
- UI渲染
- requestAnimationFrame
1.2 微任务(MicroTask)
典型场景:
- Promise.then()/catch()/finally()
注意:Promise本身的方法体是同步执行的 - MutationObserver
- process.nextTick(Node.js环境)
二、执行顺序
- 执行当前执行栈中的所有同步代码
- 执行所有微任务(直到微任务队列清空)
- 执行一个宏任务
- 更新UI渲染(如果需要)
- 重复循环
三、关键差异对比
特征 | 宏任务 | 微任务 |
---|---|---|
执行优先级 | 低 | 高 |
队列清空机制 | 每次执行一个 | 全部执行直至队列清空 |
触发机制 | EventLoop每个循环周期 | 执行栈清空后立即执行 |
典型API | setTimeout, setInterval | Promise, process.nextTick |
四、代码分析
console.log("start")setTimeout(()=>{console.log(1)
},0)
var pro = new Promise((resolve, reject)=>{resolve(2)var innerPro = new Promise((resolve, reject)=>{resolve(3)console.log(4)})innerPro.then(res=>{console.log(res)})
})
pro.then(res=>{console.log(res)
})console.log('end')/* 输出顺序:
start
4
end
3
2
1
*/
- 首先执行栈将所有同步代码进行执行,先输出"start"
- 将
setTimeout
推入宏任务队列进行等待。 pro
的方法体和innerPro
的方法体依次推入执行栈中执行,会输出"4"- 将
innerPro.then
推入微任务队列,pro.then
也推入微任务队列。微任务队列的顺序为innerPro.then -> pro.then
- 执行栈输出"end",执行栈已清空。
- 微任务队列依次清空,输出"3"和"2"
- 执行宏任务队列中的代码,输出"1"
- 流程结束
最后推荐一个JS代码执行流程可视化的网站:https://www.jsv9000.app/
#前端面试题