面试官:聊一下 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,欢迎大家学习指正!

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

相关推荐
晴殇i2 分钟前
前端内容保护:如何有效防止用户复制页面内容?
前端·javascript·css
程序猿阿伟7 分钟前
《声音的变形记:Web Audio API的实时特效法则》
开发语言·前端·php
凌览10 分钟前
有了 25k Star 的MediaCrawler爬虫库加持,三分钟搞定某红书、某音等平台爬取!
前端·后端·python
万少12 分钟前
2-自然壁纸实战教程-AGC 新建项目
前端·harmonyos
满分观察网友z23 分钟前
别小看这个滑动条!从性能灾难到用户挚爱的 uni-app Slider 踩坑实录
前端
满分观察网友z26 分钟前
别再裸写<textarea>了!一个“小”功能,我用上了它几乎所有API
前端
bemyrunningdog27 分钟前
二进制权限控制方案
javascript·react.js·ecmascript
西西木科技丨Shopify开发机构32 分钟前
如何在 Shopify 中建立重定向
前端·html
汪子熙38 分钟前
深入探析 header facets:定位与应用
前端·javascript
你听得到1140 分钟前
从需求到封装:手把手带你打造一个高复用、可定制的Flutter日期选择器
前端·flutter