一道面试题 简单理解event loop

85 阅读2分钟

一道面试题,简单理解event loop,题如下:说说执行过程以及为什么。

Promise.resolve().then(() => {
  console.log('promise1');
  const timer2 = setTimeout(() => {
    console.log('timer2')
  }, 0)
});
const timer1 = setTimeout(() => {
  console.log('timer1')
  Promise.resolve().then(() => {
    console.log('promise2')
  })
}, 0)
console.log('start');

想象JavaScript的执行环境是一个大型的游乐场,里面有两个区域:一个是“同步游乐区”,另一个是“异步等待区”。在“异步等待区”里,又分为“宏任务游乐场”和“微任务小卖部”。

  1. 进入游乐场(代码开始执行)

    • 你首先来到“同步游乐区”,看到第一个项目是console.log('start');,你立即执行它,打印出“start”。
  2. 遇到宏任务(setTimeout)

    • 你接着遇到了两个宏任务(timer1timer2setTimeout),但它们不是立即执行的,而是被放在了“宏任务游乐场”的等待队列里。尽管它们都被设置为0毫秒后执行,但JavaScript不会让它们打断当前的同步代码执行。
  3. 遇到微任务(Promise.then)

    • 然后你遇到了一个Promise.resolve().then(...),这是一个微任务。微任务就像是“微任务小卖部”里的任务,它们会在当前同步代码执行完毕后,且在下一个宏任务之前被处理。所以,你先把这个then的回调函数放在了“微任务小卖部”的队列里。
    • 当你完成所有同步代码(即“同步游乐区”的所有项目)后,你首先去“微任务小卖部”查看是否有任务需要执行。你找到了那个then的回调函数,执行它,打印出“promise1”。
    • 在这个then的回调函数里,你又遇到了一个setTimeouttimer2),同样地,它被放在了“宏任务游乐场”的等待队列里。
  4. 执行宏任务

    • 完成了“微任务小卖部”的所有任务后,你回到“宏任务游乐场”,看到timer1的回调已经在队列里了。你执行它,打印出“timer1”。
    • timer1的回调里,你又遇到了一个Promise.resolve().then(...),它的回调函数再次被放在了“微任务小卖部”的队列里。
  5. 再次执行微任务

    • 执行完timer1的回调后,你再次去“微任务小卖部”查看,找到了那个新的then的回调函数,执行它,打印出“promise2”。
  6. 执行剩余的宏任务

    • 最后,你回到“宏任务游乐场”,看到timer2的回调也已经在队列里了。你执行它,打印出“timer2”。

所以,整个执行顺序就是:

	start  
	promise1  
	timer1  
	promise2  
	timer2

图解如下:

微信截图_20240702154027.png