Event Loop
宏观描述
- js单线程依次执行事件队列里的任务
- 执行事件队列里的任务的时候压入执行栈
- 执行栈内同步执行(销毁),异步挂起(后续任务不等待),当一个异步返回结果后,js会将这个事件加入另一个队列
- 当前执行栈清空后,再次读取事件队列里的任务来执行,循环往复
Macrotask & Microtask
宏任务(macrotask): script , setTimeput, setInterval, I/O, 事件, postMessage, MessageChannel, setImmediate(node), UI rendering
微任务(microtask): Promise.then/catch, MutaionObsever, IntersectionObserver, process.nextTick(node), async/await
根据这个异步事件的类型,这个事件实际上会被分配到对应的宏任务队列或者微任务队列中去
永远都是先执行微任务,再执行宏任务
可以认为,微任务压入当前执行栈最后执行,宏任务返回结果后添加在事件队列末
优先级:process.nextTick()>Promise.then() > await , setTimeout>setImmediate
代码分析
async function async1() {
console.log('async1 start');
const async2Res = await async2();
console.log(async2Res)
await async3()
console.log('async1 end');
return 'async1 return'
}
async function async2() {
console.log('async2');
setTimeout(() => {
console.log('timeout1')
}, 0)
return Promise.resolve('promise2')
}
const async3 = async () => {
console.log('async3')
}
console.log('script start');
const promise1 = new Promise((resolve) => {
console.log('promise1');
resolve('promise1 resolve');
})
const promise3 = new Promise((resolve, reject) => {
resolve('promise3 resolve')
})
const asyncFoo = async1();
setTimeout(() => {
console.log('timeout2')
promise1.then(res => {
console.log(res)
})
asyncFoo.then(res => {
console.log(res)
})
}, 0)
promise3.then(res => {
console.log(res)
return Promise.reject('new promise3 reject')
}).catch(err => {
console.log(err)
})
setTimeout(function() {
console.log('timeout3');
}, 0)
console.log('script end');
秉承先同步后异步,先微任务后宏任务的原则。我们来分析以上代码执行。
console结果可能不准确,按F12打开控制台查看