请你谈谈:从宏任务微任务的角度谈谈js代码的执行顺序

2024-08-25 19:36

本文主要是介绍请你谈谈:从宏任务微任务的角度谈谈js代码的执行顺序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

JavaScript(JS)在浏览器环境中确实是单线程的,这主要出于以下几个原因:

  • JavaScript 的主要作用之一是处理用户的交互,如点击按钮、填写表单等。如果JavaScript是多线程的,那么在处理这些事件时可能会出现竞态条件(race
    conditions),导致用户体验的不可预测性和不一致性。例如,如果两个线程同时尝试修改同一个DOM元素,那么最终的结果将是不可预测的。

我们可以将代码大致分为同步代码(同步任务)和异步代码(异步任务)来理解和处理JavaScript中的执行流程。

  • 同步代码:立即执行,阻塞后续代码,直到执行完成。
  • 异步代码:不立即执行,放入宿主环境的任务队列中,不阻塞主线程,异步结果在将来某个时间点成为可用,并触发相应的回调函数或Promise处理程序执行。

这种异步非阻塞的模型是JavaScript能够高效处理I/O密集型任务(如网络请求、文件读写等)的关键所在。

  • 同步代码是指按照代码书写顺序依次执行的代码。当JavaScript引擎(通常指的是V8、SpiderMonkey等JavaScript解释器)遇到同步代码时,它会立即执行这些代码,并且会“原地等待”直到这些代码执行完成。这里的“原地等待”意味着JavaScript引擎会阻塞后续代码的执行,直到当前同步代码块执行完毕。

    例如,当你执行一个循环或者调用一个函数时,如果这个函数内部不包含异步操作,那么它就是一个同步任务。同步任务会立即执行,并且在下一个任务执行之前,它会完全完成。

  • 异步代码的执行则与同步代码截然不同。当JavaScript引擎遇到异步代码时,它不会立即执行这些代码,而是会将异步操作(如定时器、网络请求、文件读写等)的回调函数或Promise等异步处理机制放入宿主环境(如浏览器或Node.js)的某个任务队列(如宏任务队列或微任务队列)中。然后,JavaScript引擎会继续执行后续的代码,而不会等待异步操作的结果。

    异步操作的结果会在将来的某个时间点成为可用,此时宿主环境会将其对应的回调函数或Promise解决(resolve)或拒绝(reject)的处理程序放入JavaScript引擎的执行栈中执行。这样,即使异步操作需要花费很长时间来完成,JavaScript引擎也不会被阻塞,可以继续处理其他任务。

在JavaScript中,异步任务确实被分为了宏任务(MacroTasks)和微任务(MicroTasks)两大类。

  • 并不是所有由JavaScript引擎发起的任务都是微任务。例如,setTimeoutsetInterval虽然是由JavaScript代码发起的,但它们是由宿主环境(浏览器或Node.js)管理的宏任务。
  • 不同的JavaScript引擎(如V8、SpiderMonkey等)和宿主环境(如不同版本的浏览器或Node.js)之间,在异步任务的处理上可能存在细微的差异。因此,在编写跨平台或跨版本的JavaScript代码时,需要注意这些差异。

宏任务是由宿主环境(如浏览器或Node.js)发起的异步任务。宏任务之间的执行是串行的,即每次只能执行一个宏任务,执行完毕后才会去执行下一个宏任务。它们通常包括:

  • script(整体代码)
  • setTimeout
  • setInterval
  • setImmediate(Node.js特有)
  • I/O
  • UI渲染
  • 事件处理(如点击、滚动等)

微任务是由JavaScript引擎发起的异步任务。与宏任务不同,微任务是在当前宏任务执行完毕后,下一个宏任务开始之前执行的。而且,微任务队列中的任务会按照它们被添加到队列中的顺序依次执行,直到微任务队列为空。它们通常包括:

  • Promise.thenPromise.catchPromise.finally
  • process.nextTick(Node.js特有)
  • MutationObserver(DOM变化观察)
  1. 从上往下执行所有的同步代码
  2. 在执行过程中遇到宏任务就存放到宏任务队列中, 遇到微任务就存放到微任务队列中
  3. 当所有的同步任务执行完毕, 就执行微任务队列中满足需求的所有回调(process.nextTick 优先 )
  4. 当微任务队列中所有满足需求的回调执行完毕后, 就执行宏任务队列中满足需求的所有回调 ( SetImmediate 最后 )
    在这里插入图片描述
1 3 4 5 1000 2

在这里插入图片描述
结果执行顺序为 : 3 2 1
在这里插入图片描述
在这里插入图片描述
输出结果为:11 14 12 15 13
在这里插入图片描述
输出结果为 :2 3 6 p2 p1 1 4 5

async function async1() {console.log('async1');await async2();console.log('async1 end');
}async function async2() {console.log('async2');
}console.log('script start');
setTimeout(function () {console.log('setTimeout');
}, 0);
async1();

在这里插入图片描述

script start
async1
async2
async1 end
setTimeout

这篇关于请你谈谈:从宏任务微任务的角度谈谈js代码的执行顺序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1106461

相关文章

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

解密SQL查询语句执行的过程

《解密SQL查询语句执行的过程》文章讲解了SQL语句的执行流程,涵盖解析、优化、执行三个核心阶段,并介绍执行计划查看方法EXPLAIN,同时提出性能优化技巧如合理使用索引、避免SELECT*、JOIN... 目录1. SQL语句的基本结构2. SQL语句的执行过程3. SQL语句的执行计划4. 常见的性能优

Spring Bean初始化及@PostConstruc执行顺序示例详解

《SpringBean初始化及@PostConstruc执行顺序示例详解》本文给大家介绍SpringBean初始化及@PostConstruc执行顺序,本文通过实例代码给大家介绍的非常详细,对大家的... 目录1. Bean初始化执行顺序2. 成员变量初始化顺序2.1 普通Java类(非Spring环境)(

Spring Boot 中的默认异常处理机制及执行流程

《SpringBoot中的默认异常处理机制及执行流程》SpringBoot内置BasicErrorController,自动处理异常并生成HTML/JSON响应,支持自定义错误路径、配置及扩展,如... 目录Spring Boot 异常处理机制详解默认错误页面功能自动异常转换机制错误属性配置选项默认错误处理

如何在Java Spring实现异步执行(详细篇)

《如何在JavaSpring实现异步执行(详细篇)》Spring框架通过@Async、Executor等实现异步执行,提升系统性能与响应速度,支持自定义线程池管理并发,本文给大家介绍如何在Sprin... 目录前言1. 使用 @Async 实现异步执行1.1 启用异步执行支持1.2 创建异步方法1.3 调用

Python实现MQTT通信的示例代码

《Python实现MQTT通信的示例代码》本文主要介绍了Python实现MQTT通信的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 安装paho-mqtt库‌2. 搭建MQTT代理服务器(Broker)‌‌3. pytho

Spring Boot Maven 插件如何构建可执行 JAR 的核心配置

《SpringBootMaven插件如何构建可执行JAR的核心配置》SpringBoot核心Maven插件,用于生成可执行JAR/WAR,内置服务器简化部署,支持热部署、多环境配置及依赖管理... 目录前言一、插件的核心功能与目标1.1 插件的定位1.2 插件的 Goals(目标)1.3 插件定位1.4 核

MySQL进行数据库审计的详细步骤和示例代码

《MySQL进行数据库审计的详细步骤和示例代码》数据库审计通过触发器、内置功能及第三方工具记录和监控数据库活动,确保安全、完整与合规,Java代码实现自动化日志记录,整合分析系统提升监控效率,本文给大... 目录一、数据库审计的基本概念二、使用触发器进行数据库审计1. 创建审计表2. 创建触发器三、Java

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直