一、事件循环是什么?
首先,JS是单线程的,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环机制。在JS中把任务分为同步和异步,同步任务和异步任务的执行环境不同,同步任务会进入主线程,异步任务会进入EventQueue(事件队列),主线程中的任务执行完毕后,回去EventQueue中读取对应的任务,并推到主线程中执行,不断重复过程,称为EventLoop(事件循环机制)
- 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
- 异步任务:异步执行的任务,比如ajax网络请求、setTimeout定时函数等

二、宏任务和微任务
微任务
异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前
常见的微任务有:
- Promise.then
- Proxy对象替代
- process.nextTick
- MutaionObserver
宏任务
宏任务的时间粒度比较大,执行的时间间隔是不能精确控制的,对一些高实时性的需求就不太符合
常见的宏任务有:
- 整个script
- setTimeout/setInterval
- UI rendering/UI事件
- setImmediate、I/O
事件循环、宏任务、微任务关系:执行一个宏任务,如果遇到微任务就将它放到微任务的事件队列中,当前宏任务执行完成后,会查看微任务的事件队列,然后将里面的所有微任务依次执行完
三、题目
console.log(1);
setTimeout(()=>{
console.log(2);
},0)
new Promise((resolve, reject) => {
console.log('new Promise');
resolve();
}).then(()=>{
console.log('then');
})
console.log(3);
最终结果:1 => new Promise => 3 => then => 2
// 1、遇到console.log(1) 立即执行,直接打印 1
// 2、遇到定时器,属于新的宏任务,留着后面执行
// 3、遇到new Promise,立即执行,打印 new Promise
// 4、.then属于微任务,放入微任务队列
// 5、遇到console.log(3) 立即执行,直接打印 3
// 6、本轮宏任务执行完毕,去微任务队列中执行所有微任务 打印 then
// 7、执行新的宏任务setTimeout,打印 2
setTimeout(()=>{
console.log(2);
},0)
console.log(5);
new Promise((resolve,reject)=>{
console.log(3);
resolve();
}).then(()=>{
console.log(4);
})
fn1()
console.log('-------------------------------')
async function fn1(){
console.log(1)
await fn2()
console.log(10)
}
async function fn2(){
console.log('fn2')
}
console.log(3)
// 最终结果:
5
3
1
fn2
-------------------------------
3
4
10
2
// 遇到setTimeout宏任务,留到下一轮再执行
// console.log(5) 直接打印 5
// .then 属于微任务,放入事件队列中
// 遇到fn1(),遇到conso.log(1) 打印 1,遇到await fn2(),执行fn2(),await后面的执行延迟
// 遇到console.log('fn2') 打印fn2
// 立即执行console.log('--------')
// 立即执行 console.log(3) 打印 3
// 宏任务执行完毕,执行微任务.then 打印 4,再去执行await 后的console.log(10) 打印 10
// 最后执行setTimeout 打印 2
本文介绍了JavaScript中的事件循环机制,包括什么是事件循环,同步任务和异步任务的执行环境,以及宏任务和微任务的区别。同步任务在主线程执行,异步任务进入EventQueue。事件循环在主线程任务完成后,从EventQueue取出宏任务执行,宏任务执行过程中遇到微任务会放入微任务队列,宏任务执行完毕后再执行所有微任务。

1088

被折叠的 条评论
为什么被折叠?



