JS 事件循环(Event Loop)机制

事件循环机制的作用

事件循环机制是 JS 的一种执行机制,一种可以实现异步编程的机制。

因为 JS 是单线程的,单线程意味着所有任务需要排队执行。但是有一些 API(比如:定时器和 Ajax 等)是需要等待一定的时间才能得到结果的,如果它们按顺序执行,会造成很大的效率问题。因此,JS 采取了异步编程,凡是需要等待的操作,都会交给浏览器或 NodeJS 进行挂起,等同步代码执行完毕后再执行异步操作。这个过程就需要用到事件循环机制来进行操作的调度。

事件循环机制的原理

事件循环机制将所有代码分为同步任务和异步任务异步任务又分为宏任务和微异步。事件循环机制就是围绕同步任务、宏任务、微任务的执行时机展开的。

同步任务在调用栈中执行,异步任务在任务队列中执行。

常见的宏任务
  • 整体代码(<script>) :整个脚本代码块的执行可以视为一个宏任务
  • setTimeout / setlnterval:定时器回调函数属于宏任务
  • setlmmediate (Node.js环境): Node.js 独有的宏任务接口,表示下一次事件循环迭代开始时执行的任务
  • I/O 回调:如网络请求、文件读写等异步 I/O 操作完成后的回调函数
  • UI 渲染:浏览器环境中的渲染操作,如重绘(repaint)和回流(reflow)
  • MessageChannel:使用 MessageChannel 进行跨文档消息传递时的回调
  • MutationObserver:虽然 MutationObserver 的行为更像是微任务,但它实际上是在 UI 渲染之后执行的,可以看作是宏任务的一部分(因为它依赖于 UI 更新)
常见的微任务
  • Promise.then/catch/finally:Promise对象的回调函数。(Promise构造函数的参数中的代码是同步的,.then 回调函数的内容是异步的)
  • MutationObserver 回调:虽然它在宏任务之后执行,但其回调属于微任务
  • Process.nextTick (Node.js环境):Node.js 环境提供的微任务接口,确保回调函数在当前宏任务结束前执行
  • async/await:async function 内部的 await 表达式之后的代码块会在下一个微任务中执行

事件循环机制的执行流程

  • 初始化:当 JS 引擎启动时,首先会创建全局执行上下文并压入调用栈。初始化任务队列,包括微任务队列和宏任务队列
  • 执行同步代码:使用调用栈执行同步代码,遇到宏任务放入宏任务队列,遇到微任务放入微任务队列。
  • 执行微任务:当全局上下文中的所有同步代码执行完毕后,会首先处理所有待执行的微任务
  • 渲染(浏览器环境):清空微任务队列后,浏览器会尝试进行渲染操作,更新页面视图。
  • 执行宏任务:渲染之后,事件循环会从宏任务队列中取出一个宏任务来执行。 每个宏任务内部也会先执行其同步代码,同样遇到宏任务放入宏任务队列,遇到微任务放入微任务队列。
  • 执行微任务:若上一步宏任务中产生微任务,微任务队列不为空,需处理所有待执行的微任务
  • 渲染
  • 执行宏任务
  • 循环迭代:事件循环不断在宏任务队列和微任务队列间切换,执行任务,直至两个队列都为空

浏览器执行的时候,所有的js代码都会被解析到<script>标签中,而<script>标签又是一个宏任务,所以整个事件循环机制可以看作是在解析一个全局的宏任务。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘子味的冰淇淋~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值