事件循环是什么
js是单线程运行的,根据情况执行同步代码和异步代码
同步代码:立即执行的主线程代码,大部分代码都是同步代码
异步代码:比如网络请求、setTimeout定时函数
宏任务&微任务
异步任务分为宏任务、微任务
常见微任务:
- Promise.then
- MutaionObserver
- process.nextTick
- asnyc/await中await下方被阻塞的代码
常见宏任务:
- script (可以理解为外层同步代码)
- setTimeout/setInterval
- UI rendering/UI事件
- setImmediate、I/O
图解EventLoop
- 执行顺序
- main Script的代码(无等待的)
- 执行微任务,直至微任务队列清空
- 微任务队清空后,执行宏任务(宏任务回调中有微任务的时,依旧是清空微任务再执行宏任务)
一段经典的异步代码
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('settimeout')
})
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
- 打印'script start',遇到setTimeout丢入宏任务队列
- 执行async1函数,打印'async1 start',执行async2函数,打印‘async2’,后续代码执行遇到阻塞,即被丢入了微任务队列
- 执行new Promise函数,打印'promise1',then函数部分丢入微任务队列
- 打印'script end'
- 开始清空微任务队列,打印'async1 end',打印'promise2'
- 开始执行下一个宏任务,打印‘settimeout’
执行顺序:script start、async1 start、async2、promise1、script end、async1 end、promise2、settimeout