要想搞清楚eventloop事件循环,首先要弄清楚宏任务和微任务
宏任务:script全部,setTimeout,setInterval,setImmediate,I/O等
微任务:Process.nextTick(Node独有),Promise等
eventloop(事件循环):由三个部分祖成,调用栈(call stack)、消息队列(Message Queue)、微任务队列
eventloop运行机制:
(1)只有宏任务时:
function fn1() {
console.log(5)
setTimeout(function () {
console.log(4)
}, 0)
}
function fn2() {
console.log(6)
fn1()
console.log(7)
}
fn2(); // 6,5,7,4
运行过程:先从全局栈中一行一行执行,首先遇到fn2(),然后进入调用栈,将console.log(6)压入栈然后弹出,
遇到fn1(),再进入调用栈,遇到console.log(5),压入栈弹出,遇到setTimeout,将内容压入消息队列(消息队列
内容会在调用栈清空后再开始执行),遇到console.log(7),压入栈弹出,此时调用栈为空,再执行消息队列内容,
结果:6,5,7,4
(2)既有宏任务,又有微任务
let p = new Promise(function (resolve) {
console.log(3)
resolve()
})
function fn1() {
console.log(5)
setTimeout(function () {
console.log(4)
}, 0)
}
function fn2() {
p.then(funtion(){
console.log(1)
})
console.log(6)
fn1()
console.log(7)
}
fn2(); // 3,6,5,7,1,4
运行过程:全局栈执行fn2(),进入调用栈遇到声明的Promise对象,调用它的then()方法,遇到console.log(3)压入栈弹出,resolve将Promise状态改为successed,根据Promise状态将resolve内容(console.log(1))压入微任务队列,遇到console.log(6),压入栈弹出,进入fn(1),遇到console.log(5)压入栈弹出,遇到setTimeout将内容压入消息队列,遇到console.log(7)压入栈弹出,此时调用栈情况,微任务队列优先于消息队列执行,先执行console.log(1)再执行console.log(4)
// 结果:3,6,5,7,1,4