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

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

相关推荐
Martin -Tang32 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发33 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
老码沉思录1 小时前
写给初学者的React Native 全栈开发实战班
javascript·react native·react.js
我不当帕鲁谁当帕鲁2 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂2 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成5 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽5 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新6 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html