1. 宏任务和微任务
宏任务(macroTask)和微任务(microTask)都是异步中API的分类。
- 宏任务:setTimeout,setInterval,Ajax,DOM事件
- 微任务:Promise,async/await
微任务执行时机比宏任务要早。
console.log(100)
// 宏任务
setTimeout(()=>{
console.log(200)
})
// 微任务
Promise.resolve().then(()=>{
console.log(300)
})
console.log(400)

2. enevt loop和DOM渲染
JS是单线程的,而且和DOM渲染公用一个线程。JS执行的时候,需要留出时机用于DOM渲染。这个时机就是微任务执行后,宏任务执行前。
当Call Stack中的同步代码全部执行完毕之后,会进行DOM渲染,然后再触发event loop。

实例:当点击alert弹框的确认按钮后,才会渲染DOM元素,因为不点击确认按钮,Call Stack中的代码不会清空,就不会进行下一步:DOM渲染。
<body>
<div id="container"></div>
<script>
const $p1 = $('<p>一段文字</p>')
const $p2 = $('<p>一段文字</p>')
const $p3 = $('<p>一段文字</p>')
$('#container')
.append($p1)
.append($p2)
.append($p3)
console.log('length', $('#container').children().length)
alert('本次 call stack 结束,DOM 结构已更新,但尚未触发渲染') // alert会阻断js执行,也会阻断DOM渲染
</script>
</body>
3. 宏任务和微任务的根本区别
- 宏任务:DOM渲染后触发,如setTimeout
- 微任务:DOM渲染前触发,如Promise
<body>
<div id="container"></div>
<script>
const $p1 = $('<p>一段文字</p>')
const $p2 = $('<p>一段文字</p>')
const $p3 = $('<p>一段文字</p>')
$('#container')
.append($p1)
.append($p2)
.append($p3)
// 微任务:DOM渲染前触发
Promise.resolve().then(()=>{
console.log('lenght1', $('container').children().length)
alert('触发了微任务')
})
// 宏任务:DOM渲染后触发
setTimeout(()=>{
console.log('lenght2', $('container').children().length)
alert('触发了宏任务')
})
</script>
</body>
为什么微任务执行会更早?
可以从event loop去理解。假如程序执行的时候遇到宏任务,例如setTimeout,此时会将setTimeout中执行的代码放入Web APIs中,等到所有的同步代码执行完,以及DOM元素渲染完毕之后,执行event loop,此时Web APIs中的代码等到了时机,会移动到Callback Queue中,event loop将Callback Queue中的代码移到Call Stack中执行。
然而,当Call Stack中遇到微任务时,例如Promise,此时会将Promise执行的代码放入micro task queue。因为Promise是ES6规定的,不是W3C规定的,因此执行时放入micro task queue,micro task queue的执行是先于DOM渲染的。微任务在DOM渲染前执行,宏任务在DOM渲染后执行,因此微任务的执行早于宏任务。

4. 实例
JS代码执行的顺序:
- 首先执行同步代码;
- 同步代码执行结束后,call stack被清空,开启envet loop;
- 执行微任务;
- 触发DOM元素渲染;
- 触发enevt loop;
- 执行宏任务。
async function async1(){
console.log('async1 start') // 顺序2
await async2()
console.log('async1 end') // 顺序6
}
async function async2(){
console.log('async2') // 顺序3
}
console.log('script start') // 顺序1
setTimeout(function(){
console.log('setTimeout') // 顺序8
}, 0)
async1()
// 初始化 promise 时,传入的函数会立刻被执行
new Promise(function(resolve){
console.log('promise1') // 顺序4
resolve()
}).then(function(){
console.log('promise2') // 顺序7
})
console.log('script end') // 顺序5














![[附源码]计算机毕业设计的项目管理系统Springboot程序](https://img-blog.csdnimg.cn/1625b3d2f10e48df9a49f3079f893449.png)

![[附源码]Node.js计算机毕业设计动漫网站Express](https://img-blog.csdnimg.cn/e46bf0d5af0c489a939a36939c6e246d.png)



