宏任务 macroTask 和微任务 microTask
什么是宏任务,什么是微任务
- 宏任务:setTimeout,setInterval,Ajax,DOM事件
- 微任务:Promise async/await
- 微任务执行时机比宏任务要早(记住)
console.log(100)
// 宏任务
setTimeout(()=>{
console.log(200)
})
// 微任务
Promise.resolve().then(()=>{
console.log(300)
})
console.log(400)
// 100
// 400
// 300
// 200
event loop 和 DOM 渲染(再次回归一遍 event loop 的过程)
- JS 是单线程的,而且和 DOM 渲染共用一个线程
- JS 执行的时候,得留一些时机供 DOM 渲染
console.log('Hi')
setTimeout(function cb1(){
console.log('cb1') // cb1 即 callback
},5000)
console.log('Bye')
每次 Call Stack 清空(即每次轮询结束),即同步任务执行完;都是 DOM 重新渲染的机会,DOM 结构如有改变则重新渲染;然后再去触发下一次 Event Loop
const $p1 = '<p>一段文字</p>';
const $p2 = '<p>一段文字</p>';
const $p3 = '<p>一段文字</p>';
const $container = document.getElementById('container');
$container.append($p1)
$container.append($p2)
$container.append($p3)
// length 3
console.log('length', document.getElementById('container').children.length)
// (alert 会阻断 js 执行,也会阻断 DOM 渲染,便于查看效果)
alert('本次 call stack 结束,DOM 结构已更新,但尚未触发渲染')
微任务和宏任务的区别
- 宏任务:DOM 渲染后触发,如 setTimeout
- 微任务:DOM 渲染前触发,如 Promise,代码演示:
const $p1 = '<p>一段文字</p>';
const $p2 = '<p>一段文字</p>';
const $p3 = '<p>一段文字</p>';
const $container = document.getElementById('container');
$container.append($p1)
$container.append($p2)
$container.append($p3)
// 微任务:DOM 渲染前触发
Promise.resolve().then(()=>{
// length1 3
console.log('length1',document.getElementById('container').children.length)
alert('Promise then') // DOM 渲染了吗? - No
})
// 宏任务:DOM 渲染后触发
setTimeout(()=>{
// length2 6
console.log('length2',document.getElementById('container').children.length)
alert('setTimeout') // DOM 渲染了吗? - Yes
})
从 event loop 解释,为何微任务执行更早?
- 微任务是 ES6 语法规定的
- 宏任务是由浏览器规定的