Javascript事件循环流程分析

基础概念

事件循环(Event Loop):事件循环是JavaScript运行时环境中的一个循环机制,它不断地检查调栈用和任务队列。当调用栈为空时,事件循环会首先检查微任务队列,并执行其中的所有任务。只有当微任务队列为空时,事件循环才会检查任务队列,并执行其中的任务。

  • 同步代码首先执行。
  • 宏任务和微任务分别被添加到各自的队列中。
  • 执行栈为空后,先执行所有微任务,再执行一个宏任务。
  • 事件循环不断重复这个过程,直到没有任务需要执行。

调用栈

为什么用栈?想想函数内调用其他函数,要等内部函数执行完成才继续执行剩余的外部函数。

    在JavaScript中,调用栈(Call Stack)是一个LIFO(后进先出)结构,用于管理函数调用及其执行上下文。每当一个函数被调用时,一个新的执行上下文会被创建并推入调用栈中;当函数执行完毕后,其执行上下文会从调用栈中弹出。

以下是调用栈内容如何加入和移除的详细过程:

  1. 全局执行上下文
    • JavaScript代码开始执行时,会首先创建一个全局执行上下文(Global Execution Context)。这个上下文在整个程序的生命周期内始终存在,并且作为调用栈的底部。
  2. 函数调用
    • 当一个函数被调用时,会创建一个新的执行上下文(Function Execution Context),并将其推入调用栈中。
    • 每个执行上下文包含以下三个主要部分:
      • 变量对象(Variable Object, VO):存储变量和函数声明。在ES6之后,这个概念被更现代的词法环境(Lexical Environment)和变量环境(Variable Environment)所替代。
      • 作用域链(Scope Chain)保证对上级作用域中的变量和函数的访问
      • this:函数被调用时绑定的this值。
  3. 执行上下文创建和推入调用栈
    • 创建一个新的执行上下文。
    • 将这个新的执行上下文推入调用栈。
    • 执行上下文中的变量和函数声明会被提升(hoisting)。
    • 如果函数中有参数,参数也会被初始化。
    • this值被确定。
  4. 函数执行
    • 执行函数体内的代码。
    • 如果函数内部调用了其他函数,那么会重复步骤2和3,为被调用的函数创建新的执行上下文并推入调用栈。
  5. 函数完成
    • 当函数执行完毕后,其执行上下文会从调用栈中弹出。
    • 如果函数返回了一个值,这个值会被传递给调用者。
  6. 调用栈为空
    • 当调用栈为空时,JavaScript引擎认为当前代码执行完毕,可能会开始执行事件循环中的任务(如异步回调)。
​
function outerFunction() {
    console.log('Outer function start');
    
    function innerFunction() {
        console.log('Inner function start');
        // Some code...
        console.log('Inner function end');
    }
    
    innerFunction();
    
    console.log('Outer function end');
}

outerFunction();

​
调用栈的变化:
  1. 全局执行上下文被推入调用栈。
  2. outerFunction 被调用,创建 outerFunction 的执行上下文并推入调用栈。
  3. outerFunction 打印 Outer function start
  4. innerFunction 被调用,创建 innerFunction 的执行上下文并推入调用栈。
  5. innerFunction 打印 Inner function start 和 Inner function end
  6. innerFunction 执行完毕,其执行上下文从调用栈中弹出。
  7. outerFunction 继续执行,打印 Outer function end
  8. outerFunction 执行完毕,其执行上下文从调用栈中弹出。
  9. 全局执行上下文始终是调用栈的底部,此时调用栈为空。

宏任务和微任务

  •  微任务队列:它专门用于处理如Promiseresolvereject回调、async/await、和MutationObserver等微任务。微任务的优先级高于宏任务。
  • 宏任务队列:用来存储准备好执行的回调函数,比如setTimeoutsetInterval的回调

Promise.resolve().then(() => {
  console.log('outerPromise');
  const innerTimer = setTimeout(() => {
    console.log('innerTimer')
  }, 0)
});

const timer1 = setTimeout(() => {
  console.log('outerTimer')
  Promise.resolve().then(() => {
    console.log('innerPromise')
  })
}, 0)
console.log('run');

JavaScript代码示例

javascript复制代码

console.log('Script start');


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


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


console.log('Script end');

事件循环执行过程描述

  1. 全局执行上下文创建
    • 当JavaScript引擎开始执行这段脚本时,它会首先创建一个全局执行上下文。这个上下文包含了全局对象(在浏览器中通常是window对象)以及脚本中声明的所有变量和函数。
  2. 同步代码执行
    • 引擎开始执行全局执行上下文中的同步代码。
    • 首先,打印出'Script start'
  3. 宏任务队列(Macro Task Queue)
    • 当遇到setTimeout时,JavaScript引擎不会立即执行其回调函数,而是将回调函数包装成一个宏任务,并将其添加到宏任务队列中。setTimeout的延迟时间设置为0,但这并不意味着回调函数会立即执行;它只会在下一个事件循环迭代中被执行。
  4. 微任务队列(Micro Task Queue)
    • 当遇到Promise.resolve().then(...)时,then方法中的回调函数会被包装成一个微任务,并添加到微任务队列中。微任务队列中的任务会在当前执行栈为空后、下一个宏任务执行之前被立即执行。
  5. 继续同步代码执行
    • 接下来,打印出'Script end'
    • 此时,全局执行上下文中的同步代码已经执行完毕,执行栈为空。
  6. 微任务执行
    • 在执行下一个宏任务之前,JavaScript引擎会检查微任务队列。由于我们有一个微任务(即Promise的回调函数),引擎会执行这个微任务。
    • 打印出'Promise callback'
  7. 宏任务执行
    • 微任务队列为空后,JavaScript引擎会从宏任务队列中取出下一个任务来执行。在这个例子中,宏任务队列中有一个由setTimeout添加的回调函数。
    • 执行这个回调函数,并打印出'Timeout callback'
  8. 事件循环继续
    • 如果此时没有其他宏任务或微任务需要执行,事件循环可能会等待新的异步事件(如用户输入、网络请求等)来触发新的任务添加到任务队列中。
    • 一旦有新的事件触发,相应的回调函数会被添加到宏任务队列或微任务队列中,并等待事件循环的下一个迭代来执行。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/912030.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

单元/集成测试解决方案

在项目开发的前期针对软件单元/模块功能开展单元/集成测试,可以尽早地发现软件Bug,避免将Bug带入系统测试阶段,有效地降低HIL测试的测试周期,也能有效降低开发成本。单元/集成测试旨在证明被测软件实现其单元/架构设计规范、证明被…

【C++】C++的单例模式、跟踪内存分配的简单方法

二十四、C的单例模式、跟踪内存分配的简单方法 1、C的单例模式 本小标题不是讨论C的语言特性,而是一种设计模式,用于确保一个类在任何情况下都只有一个实例,并提供一个全局访问点来获取这个实例。即C的单例模式。这种模式常用于资源管理&…

LangGPT结构化提示词编写实践

基础任务 如果直接询问大模型strawberry有几个r,大模型会给出错误的答案: 这里我们引入思维连Chain of Thought,我们让大模型遍历一遍单词,每次累加得到最终结果 之前怎么都做不对的题,让大模型一步一步思考&#xf…

【Python系列】使用 Poetry 进行 Python 项目管理

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Linux内核USB2.0驱动框架分析--USB设备枚举过程

一 USB特点 1.1 USB协议版本介绍: USB1.0/1.1(low/fullspeed):传输速率最大为12Mbps,是较早的USB协议版本。 USB2.0(highspeed):传输速率最大为480Mbps,相比USB1.0/1.1…

解决ultralytics的YOLO模型训练中验证集Loss为NaN(或mAP为0)的问题

前言 在使用ultralytics库的YOLO模型时,比如YOLOv8进行目标检测模型训练,遇到一个非常奇怪的问题:训练过程中的验证损失(loss)出现了NaN,而验证的评价指标如mAP50却能正常计算(有时mAP都也为0&…

微信支付现金红包,实现转账到零钱包功能

大家好,我是小悟。 上次说到微信商家转账到零钱要出新玩法,可能会对某些特定的业务产生影响,详细请阅读【微信商家转账到零钱新玩法,却是个不好接受的消息】。 微信支付还有个现金红包的产品,也可以实现转账到用户零…

掌握均值回归,外汇交易盈利新视角

外汇交易是全球金融市场的重要组成部分,它不仅用于国际间结算债权债务,还提供了一个充满盈利机会的金融市场。在这个市场中,货币价格的波动为投资者带来了丰富的交易机会。本文,EagleTrader将详细介绍外汇交易中的一种常用策略——…

mac-泛洪

泛洪攻击的类型 TCP SYN Flood: 攻击者向目标服务器发送大量的 TCP SYN 请求,但不完成握手过程。服务器为每个请求分配资源,最终可能耗尽其连接表,导致无法处理正常请求。 UDP Flood: 攻击者向目标发送大量的 UDP 数据…

【Windows修改Docker Desktop(WSL2)内存分配大小】

记录一下遇到使用Docker Desktop占用内存居高不下的问题 自从使用了Docker Desktop,电脑基本每天都需要重启,内存完全不够用,从16g扩展到24,然后到40G,还是不够用;打开Docker Desktop 运行时间一长&#x…

【06】A-Maven项目SVN设置忽略文件

做Web项目开发时,运用的是Maven管理工具对项目进行管理,在项目构建的过程中自动生成了很多不需要SVN进行管理的文件,SVN在对源码进行版本管理时,需要将其忽略,本文给出了具体解决方案。 SVN设置忽略Maven项目中自动生成…

【数据分享】2024年我国省市县三级的生活服务设施数量(46类设施/Excel/Shp格式)

人才市场、售票处、旅行社等生活服务设施的配置情况是一个城市公共基础设施完善程度的重要体现,一个城市生活服务设施种类越丰富,数量越多,通常能表示这个城市的公共服务水平越高! 本次我们为大家带来的是我国各省份、各地级市、…

【算法】Floyd多源最短路径算法

目录 一、概念 二、思路 三、代码 一、概念 在前面的学习中,我们已经接触了Dijkstra、Bellman-Ford等单源最短路径算法。但首先我们要知道何为单源最短路径,何为多源最短路径 单源最短路径:从图中选取一点,求这个点到图中其他…

【商用存储】希捷磁盘阵列部署实践

文章目录 一、前言1、盘阵类型2、性能规格 二、功能说明1、RAID配置1.1、虚拟池(virtual pool)1.2、线性池(linear pool) 2、磁盘休眠2.1、RBOD2.1.1、功能说明2.1.2、规格限制 3、ADAPT配置3.1、说明3.2、规格限制3.3、配置建议3…

Android Room框架使用指南

Room框架使用指南 项目效果创建应用,配置Gradle1、在app Module的build.gradle配置kapt插件2、配置依赖:3、配置依赖包版本号创建实体类创建DAO1、DAO简介2、WordDao设计以及相关注解说明3、监听数据变化添加Room数据库1、Room数据库简介2、实现Room数据库实现存储库实现View…

Read excerpt(eighteen)——The hidden value of Corporate Social Responsibility

“There is one and only one social responsibility of businesses,” wrote Milton Friedman, a Nobel prize-winning economist, “That is, to use its resources and engage in activities …

纯血鸿蒙系统 HarmonyOS NEXT自动化测试实践

1、测试框架选择 hdc:类似 android 系统的 adb 命令,提供设备信息查询,包管理,调试相关的命令ohos.UiTest:鸿蒙 sdk 的一部分,类似 android sdk 里的uiautomator,基于 Accessibility 服务&…

基于java宠物医院管理系统的设计与实现

一、环境信息 开发语言:JAVA JDK版本:JDK8及以上 数据库:MySql5.6及以上 Maven版本:任意版本 操作系统:Windows、macOS 开发工具:Idea、Eclipse、MyEclipse 开发框架:SpringbootHtmljQueryMysql…

施工企业为什么要用工程项目管理软件?工程项目管理软件的用处是什么?

施工企业一定会遇到哪些问题?工人怠工、材料浪费、数据造假、工期拖延、质量问题、安全隐患等。这些问题正在悄然侵蚀建施工业的经济效益。每一个环节的失控都可能导致巨大的经济损失,还可能损害企业的声誉。面对日益复杂的工程管理环境,如何…

业务模块部署

一、部署前端 1.1 window部署 下载业务模块前端包。 (此包为耐威迪公司发布,请联系耐威迪客服或售后获得) 包名为:业务-xxxx-business (注:xxxx为发布版本号) 此文件部署位置为:……