事件循环机制是如何工作的

简介: 【8月更文挑战第3天】事件循环机制是如何工作的

事件循环机制(Event Loop)在JavaScript中扮演着至关重要的角色,特别是在处理异步事件和回调时。以下是事件循环机制如何工作的详细解释:

1. 基本组成

事件循环机制主要由以下几个部分组成:

  • 执行栈(Call Stack):用于存储待执行的同步任务(如函数调用)。它是一个后进先出(LIFO)的数据结构,遵循先进后出的原则。
  • 任务队列(Task Queue):也称为宏任务队列,用于存放等待被执行的宏任务。宏任务包括setTimeout、setInterval、I/O操作、UI渲染等。
  • 微任务队列(Microtask Queue):用于存放等待被执行的微任务。微任务包括Promise的回调、MutationObserver的回调、async/await(当await后面跟的是一个Promise时)等。

2. 工作流程

事件循环机制的工作流程可以归纳为以下几个步骤:

  1. 执行同步代码

    • 当JavaScript引擎开始执行脚本时,它会将脚本中的所有同步代码依次放入执行栈中执行。
  2. 处理异步操作

    • 当遇到异步操作时(如setTimeout、Promise等),JavaScript引擎会将异步操作的结果或回调放入对应的任务队列(宏任务或微任务)中。
  3. 检查执行栈

    • 当执行栈为空时(即所有同步代码执行完毕),事件循环会开始工作。
  4. 执行微任务

    • 事件循环首先会检查微任务队列是否有任务需要执行。如果有,它会将微任务队列中的所有任务依次取出并执行,直到微任务队列为空。
  5. 执行宏任务

    • 在微任务队列为空后,事件循环会检查宏任务队列是否有任务需要执行。它会从宏任务队列中取出一个任务放入执行栈中执行。
  6. 重复执行

    • 上述过程会不断重复,直到执行栈为空且任务队列(包括宏任务队列和微任务队列)也为空。

3. 注意事项

  • 微任务和宏任务的执行顺序:在每次事件循环中,总是先执行微任务队列中的所有任务,然后再执行一个宏任务。这个过程会一直重复,直到所有任务都被执行完毕。
  • 渲染时机:浏览器在微任务队列为空且执行栈也为空时,会进行页面渲染。这意味着如果微任务队列中有任务,页面渲染会被延迟。
  • 避免长时间运行的任务:如果一个任务执行时间过长,会阻塞事件循环,导致其他任务无法执行。为了避免这种情况,可以将长时间的任务拆分成多个小任务,使用setTimeout或setInterval分批执行。

4. 示例

考虑以下代码示例:

console.log('1');

setTimeout(() => {
   
    console.log('setTimeout');
}, 0);

Promise.resolve().then(() => {
   
    console.log('Promise');
});

console.log('2');

// 输出结果
// 1
// 2
// Promise
// setTimeout

在这个例子中,console.log('1')console.log('2')是同步代码,会立即执行。setTimeout是一个宏任务,被放入宏任务队列中等待执行。Promise.resolve().then()是一个微任务,被放入微任务队列中等待执行。由于事件循环先执行微任务再执行宏任务,所以Promise的回调会在setTimeout的回调之前执行。

综上所述,事件循环机制是JavaScript异步编程的基石,它通过执行栈、任务队列和微任务队列的协作,实现了非阻塞的异步操作。

目录
相关文章
|
设计模式 负载均衡 网络协议
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
527 0
|
8月前
|
Java Docker 微服务
SpringBoot微服务打包Docker镜像
SpringBoot微服务打包Docker镜像
184 11
|
10月前
|
Ubuntu Linux
在Linux中,如何升级系统内所有已安装软件包?
在Linux中,如何升级系统内所有已安装软件包?
|
12月前
|
JavaScript 前端开发
WebView2 控件(基于 Microsoft Edge (Chromium) 的嵌入式浏览器控件),获取网页加载后的标题
在使用 WebView2 控件(基于 Microsoft Edge (Chromium) 的嵌入式浏览器控件)时,要获取网页加载后的标题,可以监听 WebView2 的 NavigationCompleted 事件。这个事件被触发时,表示导航已完成,此时执行JavaScript代码可以安全地获取网页的标题。
WebView2 控件(基于 Microsoft Edge (Chromium) 的嵌入式浏览器控件),获取网页加载后的标题
【qt】QSplitter 分裂器
【qt】QSplitter 分裂器
322 0
|
算法 Linux 数据安全/隐私保护
【Linux | C++ 】生产者消费者模型(Linux系统下C++ 代码模拟实现)
【Linux | C++ 】生产者消费者模型(Linux系统下C++ 代码模拟实现)
366 0
|
测试技术
notepad++安装HexEditor插件查看二进制文件
有时候我们需要分析二进制文件,但是分析二进制文件直接用编辑器查看会出现乱码的情况,本文在 notepad++ 软件上安装一个 HexEditor 插件,可方便分析二进制文件。
886 0
|
移动开发 前端开发
ruoyi-nbcio-plus基于vue3的flowable扩展属性的升级修改
ruoyi-nbcio-plus基于vue3的flowable扩展属性的升级修改
182 0
|
JavaScript UED
Vue中的路由懒加载有哪些优缺点?
Vue中的路由懒加载有哪些优缺点?
224 3
|
存储 Linux 程序员
x86的内存寻址方式
在16位的8086时代,CPU为了能寻址超过16位地址能表示的最大空间(因为 8086 的地址线 20 位而数据线 16 位),引入了段寄存器。通过将内存空间划分为若干个段(段寄存器像 ds、cs、ss 这些寄存器用于存放段基址),然后采用段基地址+段内偏移的方式访问内存,这样能访问1MB的内存空间了。