面试官:聊一下 Event - Loop

在面试中,被问及关于 JS 的 Event Loop 是相当常见的情况。理解 Event Loop 不仅是展示对 异步编程核心原理的理解,同时也展示了对浏览器环境下代码执行机制的掌握程度。

本文将深入浅出地探讨 Event Loop 的引入、概念及执行过程。

什么是 Event Loop?

Event Loop,即事件循环,是 JavaScript 异步编程的核心机制。它是一个持续运行的进程,负责监听执行栈和消息队列(任务队列),确保代码的执行顺序和异步任务的准确执行。

通俗来讲,它就是一个规则,代码会按照这个规则执行下去,不至于被某个需要等待的任务阻塞。

为什么会担心任务阻塞 ?

JS 设计之初是为了实现与用户动态交互的网页,为了能有更好的用户体验,不需占用太多资源,让交互更流畅,从而设计成了单线程

这样的设计简化了编程模型,减少了许多复杂的并发问题,但也引入了一个潜在的问题:同步任务执行时间过长可能导致任务阻塞

如何避免任务阻塞

为了解决任务阻塞的问题,JS 引入了 异步任务事件循环机制 。异步任务通常包括定时器、事件监听器等。当遇到异步任务时,它会被放入任务队列中,而不会立即执行。主线程在执行完当前的同步任务后,会检查任务队列,将等待执行的异步任务取出来执行。

异步任务

想象一下你在餐馆点餐。如果你点了一个需要等待一段时间才能做好的菜,而你不想傻坐在那里等,你可能会继续看菜单,聊天,或者做其他事情。当你点的菜做好了,服务员会把它端到你的桌子上。在这个等待的过程中,你并不需要一直盯着厨房等待,可以去做其他的事情,等待结束后再回来处理这个菜。

在编程中,异步任务就是这样的一个概念。当你执行一个异步任务时,不需要等待它完成,而是继续执行后面的代码。当异步任务完成时,系统会通知你,然后你可以处理它的结果。这样可以充分利用时间,不让程序在等待某些操作的同时停滞不前。

异步任务又分为 宏任务(macrotask)微任务(microtask),它们分别代表着不同的异步执行上下文。

1. 宏任务

常见的宏任务有:

  • script 代码
  • setTimeout
  • setInterval
  • I/O 操作
  • UI 渲染
  • ······

2. 微任务

常见的微任务有:

  • Promise.then() 注:Promise本身是同步任务
  • Async/await
  • MutationObserver 监听DOM变化
  • process.nextTick
  • ······

事件循环的执行顺序

  1. 当JS引擎拿到要执行的代码时,就算进入第一次事件循环,开始执行同步代码(这属于宏任务,因为script内的代码都属于宏任务),同步代码被推入执行栈,并执行;
  2. 当执行栈为空,查看微任务队列中是否有待执行的任务;
  3. 如果微任务队列中有任务,将微任务从队列中取出,推入执行栈,开始执行;
  4. 如果有需要,会渲染页面;
  5. 查看宏任务队列,推入执行栈,执行宏任务,开始下一轮事件循环。

举个栗子🌰

下面代码的打印顺序是怎样的呢?

js 复制代码
console.log('start');
setTimeout(()=>{
    console.log('setTimeout');
    setTimeout(()=>{
        console.log('inner');
    })
    console.log('end');
},1000)
new Promise((resolve,reject)=>{
    console.log('Promise');
    resolve()
}).then(()=>{
    console.log('then1');
}).then(()=>{
    console.log('then2');
})

【答案】(点击展开) start

Promise

then1

then2

setTimeout

end

inner

首先我们对各任务进行划分:

进入第一次事件循环,开始执行同步任务,这时候start和Promise的打印分别进栈并打印,随后出栈,宏任务进入宏任务队列,微任务进入微任务队列。

同步任务执行完后,栈为空,将微任务队列的任务依次推入执行栈执行,分别打印then1,then2。

微任务执行完毕,将宏任务推入执行栈执行,也算第二次事件循环的开始。

第二次事件循环开始,重复上述步骤,同步任务先执行,分别打印setTimeout和end。

微任务队列为空,直接执行宏任务,开始第三次事件循环,打印同步任务console.log('inner')。

所以最终打印结果为:

start

Promise

then1

then2

setTimeout

end

inner

结语

在面试中,对 Event-Loop 的理解也成为评估一个开发者JS能力的重要标准,充分展示了个人对异步编程核心原理的理解。希望这篇文章能够帮助你更好地理解和运用JS的事件循环机制。

最后

看到这里你已经能够准确回答面试官的问题了,那么在后面的文章中,我会针对事件循环机制,再出一期面试题相关的内容,如果你对此感兴趣,可以关注我后面的文章!

已将学习代码上传至github,欢迎大家学习指正!

技术小白记录学习过程,有错误或不解的地方还请评论区留言,如果这篇文章对你有所帮助请 "点赞 收藏+关注" ,感谢支持!!

相关推荐
掘金安东尼3 分钟前
蔚来 600 亿研发成本,信还是不信。。
面试·程序员·github
yinke小琪9 分钟前
JavaScript DOM节点操作(增删改)常用方法
前端·javascript
枣把儿13 分钟前
Vercel 收购 NuxtLabs!Nuxt UI Pro 即将免费!
前端·vue.js·nuxt.js
望获linux14 分钟前
【Linux基础知识系列】第四十三篇 - 基础正则表达式与 grep/sed
linux·运维·服务器·开发语言·前端·操作系统·嵌入式软件
爱编程的喵16 分钟前
从XMLHttpRequest到Fetch:前端异步请求的演进之路
前端·javascript
喜欢吃豆19 分钟前
深入企业内部的MCP知识(三):FastMCP工具转换(Tool Transformation)全解析:从适配到增强的工具进化指南
java·前端·人工智能·大模型·github·mcp
豆苗学前端22 分钟前
手把手实现支持百万级数据量、高可用和可扩展性的穿梭框组件
前端·javascript·面试
不见_22 分钟前
不想再写周报了?来看看这个吧!
前端·命令行
yinke小琪24 分钟前
JavaScript 事件冒泡与事件捕获
前端·javascript
pany26 分钟前
写代码的节奏,正在被 AI 改写
前端·人工智能·aigc