前端面试之事件循环机制

一、事件循环是什么?

首先,JS是单线程的,意味着同一时间内只能做一件事,但是这并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环机制。在JS中把任务分为同步和异步,同步任务和异步任务的执行环境不同,同步任务会进入主线程,异步任务会进入EventQueue(事件队列),主线程中的任务执行完毕后,回去EventQueue中读取对应的任务,并推到主线程中执行,不断重复过程,称为EventLoop(事件循环机制)

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
  • 异步任务:异步执行的任务,比如ajax网络请求、setTimeout定时函数等
    前端面试之事件循环机制_第1张图片

二、宏任务和微任务

微任务

异步执行的函数,执行时机是在主函数执行结束之后、当前宏任务结束之前

常见的微任务有:

  • 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)