JS事件循环-微任务-宏任务
在JS中,事件循环是一种非常重要的机制。通过事件循环,我们可以更好地实现代码的异步执行。了解JS事件循环的机制,也是在前端开发中非常必要的一项知识。
事件循环机制
事件循环机制是指JS引擎处理JS代码的一种机制。简单来说,JS引擎在执行JS代码时,会按照特定的顺序去处理事件,而这个顺序就是事件循环。与此同时,JS引擎还会把这些事件分成两类:微任务和宏任务。
微任务和宏任务
微任务
微任务是一种比较“轻量级”的事件,它的执行时间一般比较短,并且微任务的执行顺序也比较靠前,即在下一个事件循环执行之前执行。微任务包括以下几种:
- Promise
- process.nextTick (Node.js)
- MutationObserver (浏览器)
宏任务
宏任务是一种比较“重量级”的事件,它的执行时间可能会比较长,并且宏任务的执行顺序也比较靠后,即在下一个事件循环执行之后执行。宏任务包括以下几种:
- setTimeout
- setInterval
- setImmediate (Node.js)
- requestAnimationFrame (浏览器)
- I/O (Node.js)
事件循环流程
事件循环的流程大致分为以下几步:
- 首先,JS引擎会从宏任务队列中取出一个任务执行,如果宏任务队列为空,则会执行微任务队列中的所有任务。
- 接着,JS引擎会处理微任务队列中的所有任务,并且把新产生的微任务加入微任务队列中。
- 然后,JS引擎会处理宏任务队列中的下一个任务,如果宏任务队列中还有任务,则重复第1~3步,直到宏任务队列为空为止。
示例
示例一
console.log('start')
setTimeout(() => {
console.log('timer1')
Promise.resolve().then(() => {
console.log('promise1')
})
}, 0)
setTimeout(() => {
console.log('timer2')
Promise.resolve().then(() => {
console.log('promise2')
})
}, 0)
Promise.resolve().then(() => {
console.log('promise3')
})
console.log('end')
输出结果为:
start
end
promise3
timer1
promise1
timer2
promise2
代码执行过程分析:
- 执行
console.log('start')
- 执行第1个
setTimeout()
,将timer1
任务放入宏任务队列 - 执行第2个
setTimeout()
,将timer2
任务放入宏任务队列 - 执行
Promise.resolve().then(() => { console.log('promise3') })
,将promise3
任务放入微任务队列 - 执行
console.log('end')
- 触发下一轮事件循环,第1个宏任务队列中取出
timer1
任务执行,将promise1
任务放入微任务队列 - 微任务队列中取出
promise3
任务执行 - 触发下一轮事件循环,第1个宏任务队列中没有任务,执行微任务队列中的
promise1
任务并将promise2
任务放入微任务队列 - 微任务队列中取出
promise2
任务执行
示例二
console.log('start')
setTimeout(() => {
console.log('timer1')
Promise.resolve().then(() => {
console.log('promise1')
})
}, 0)
Promise.resolve().then(() => {
console.log('promise2')
})
console.log('end')
输出结果为:
start
end
promise2
timer1
promise1
代码执行过程分析:
- 执行
console.log('start')
- 执行
setTimeout()
,将timer1
任务放入宏任务队列 - 执行
Promise.resolve().then(() => { console.log('promise2') })
,将promise2
任务放入微任务队列 - 执行
console.log('end')
- 触发下一轮事件循环,第1个宏任务队列中取出
timer1
任务执行,将promise1
任务放入微任务队列 - 微任务队列中取出
promise2
任务执行 - 微任务队列中取出
promise1
任务执行
面试题分析
以下是一道经典的面试题:
console.log('1')
setTimeout(() => {
console.log('2')
}, 0)
Promise.resolve().then(() => {
console.log('3')
})
console.log('4')
输出结果是: 1 4 3 2
这个面试题考察了对事件循环机制的掌握。我们可以根据上述的分析过程,来解释这个题目的输出结果。
- 执行
console.log('1')
- 执行
setTimeout()
,将2
任务放入宏任务队列 - 执行
Promise.resolve().then(() => { console.log('3') })
,将3
任务放入微任务队列 - 执行
console.log('4')
- 触发下一轮事件循环,第1个宏任务队列中取出
2
任务执行 - 微任务队列中取出
3
任务执行
因此,输出结果为:1 4 3 2
。
综上所述,我们必须掌握JS事件循环机制以及微任务和宏任务的区别,这是学习JS中异步编程非常重要的一步。在面试中,对于事件循环机制和异步编程的问题,也是非常常见的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS事件循环-微任务-宏任务(原理讲解+面试题分析) - Python技术站