同步任务
主线程上排队执行的那些任务,只有前一个任务执行完毕,才能执行后一个任务
异步任务
由JavaScript 委托给宿主环境进行执行的任务,当异步任务执行完成后,会通知JavaScript 主线程执行异步任务的回调函数
宏任务
- script(整体代码)
- setTimeout
- setInterval
- setImmediate
- I/O
- UI render
微任务
- promise
- nextTick
- Async/Await(实际就是promise)
- MutationObserver(html5新特性)
事件循环
执行栈在执行完同步任务后,查看执行栈是否为空,如果执行栈为空,就会去检查微任务队列是否为空,如果为空的话,就执行宏任务,否则就一次性执行完所有微任务。
每次单个宏任务执行完毕后,检查微任务(microTask)队列是否为空,如果不为空的话,会按照先入先出的规则全部执行完微任务(microTask)后,设置微任务(microTask)队列为null,然后再执行宏任务,如此循环。
注意
Promise避坑
new Promise(() => {}).then()
前面的 new Promise() 这一部分是一个构造函数,这是一个同步任务
后面的 .then() 才是一个异步微任务
console.log('1')
setTimeout(function callback(){
console.log('2')
}, 1000)
new Promise((resolve, reject) => {
console.log('3')
resolve()
})
.then(res => {
console.log('4');
})
console.log('5')
执行结果:1,3,5,4,2
async/await避坑
setTimeout(() => console.log(4))
async function test() {
console.log(1)
await Promise.resolve()
console.log(2)
}
test()
console.log(3)
执行结果:1,3,2,4
可以理解为,await 以前的代码,相当于与 new Promise 的同步代码,await 以后的代码相当于 Promise.then的异步代码。
总结:执行栈-->同步任务-->微任务-->宏任务-->执行栈-->新任务