Gradle依赖管理:编译时和运行时依赖的区别

🌷🍁 博主猫头虎 带您 Go to New World.✨🍁
🦄 博客首页——猫头虎的博客🎐
🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺
🌊 《IDEA开发秘籍专栏》学会IDEA常用操作,工作效率翻倍~💐
🌊 《100天精通Golang(基础入门篇)》学会Golang语言,畅玩云原生,走遍大小厂~💐

🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥

在这里插入图片描述

文章目录

  • Gradle依赖管理:编译时和运行时依赖的区别
    • 一. 引言
      • 1)为何我们讨论Gradle依赖
      • 2)Gradle在现代开发中的重要性
    • 二. Gradle简介
      • 1)什么是Gradle
      • 2)Gradle的基本功能
    • 三. 依赖管理简介
      • 1)为何依赖管理对于项目至关重要
      • 2)如何手动处理依赖和其中的挑战
    • 四. 编译时依赖
      • 1)定义:什么是编译时依赖
      • 2)为何我们需要编译时依赖
      • 3)如何在Gradle中声明编译时依赖
      • 4)实际示例
    • 五. 运行时依赖
      • 1)定义:什么是运行时依赖
      • 2)为何我们需要运行时依赖
      • 3)如何在Gradle中声明运行时依赖
      • 4)实际示例
    • 六. 编译时与运行时依赖的区别
      • 1)对比二者的主要差异
      • 2)解释为何某些库可能仅在编译时需要,而其他库可能在运行时需要
      • 3)举例说明这些差异
    • 七. 常见问题和陷阱
      • 1)讨论关于编译时和运行时依赖的常见误区
      • 2)如何避免这些问题
    • 八. 最佳实践
      • 1)如何最优化地管理Gradle的编译时和运行时依赖
      • 2)实际的例子和提示
    • 九. 总结
      • 1)编译时和运行时依赖的重要性和区别
      • 2)为何好的依赖管理对于项目成功至关重要
    • 十. 参考资料
    • 十一. 互动/评论区
  • 原创声明

Gradle依赖管理:编译时和运行时依赖的区别


摘要:
本文详细探讨了Gradle中编译时和运行时依赖的概念、区别及其重要性。我们也将了解为什么依赖管理对于现代软件开发至关重要,并探讨了一些常见的陷阱和最佳实践。


引言:
在软件开发的世界中,依赖管理始终是一个核心议题。特别是在现代的构建工具如Gradle中,了解如何有效地管理依赖不仅可以确保代码的稳定性,还可以避免许多常见的问题。这篇文章的目的是深入探讨Gradle的编译时和运行时依赖,帮助开发者更好地理解并应用这些概念。


导语:
你是否曾在Gradle项目中纠结于编译时和运行时依赖?或者想知道为何某些库在代码编译时是必要的,而在运行时则完全无关紧要?这篇文章将带你深入了解这两种依赖的核心区别,并为你提供一些关于如何优化你的Gradle依赖管理的实用建议。

一. 引言

1)为何我们讨论Gradle依赖

在软件开发中,依赖管理始终是一个核心议题。随着项目规模的增长和外部库的广泛使用,如何管理这些库和工具变得至关重要。Gradle作为一个强大的自动化构建工具,为开发者提供了高效、灵活的依赖管理解决方案。通过讨论Gradle依赖,我们不仅可以优化我们的开发流程,还可以更好地理解项目间的依赖关系。

2)Gradle在现代开发中的重要性

Gradle已经成为许多大型企业和开源项目的首选构建工具。其在现代开发中的重要性不仅仅因为它提供的强大功能,更在于它的高度自定义性和可扩展性。此外,与其他构建工具相比,Gradle提供了更加直观的依赖管理和构建流程定义,使得开发者可以更加专注于编码,而不是花费大量时间处理构建和依赖问题。此外,Gradle还与许多现代CI/CD工具完美集成,为持续集成和持续交付提供了坚实的基础。

通过深入了解Gradle及其在依赖管理中的角色,开发者可以更加高效地进行开发,并确保项目的稳定性和可维护性。

二. Gradle简介

1)什么是Gradle

Gradle是一个开源的构建自动化工具,设计用来支持多种语言和平台,包括Java, Kotlin, C++, Android等。它采用了基于Groovy的领域特定语言 (DSL) 来描述构建逻辑,相比于传统的XML方式,这使得构建脚本更加简洁和易于理解。Gradle结合了Apache Ant的灵活性和Apache Maven的依赖管理能力,提供了一个强大、高性能且高度可定制的构建平台。

2)Gradle的基本功能

  • 依赖管理: Gradle允许开发者自动化地下载所需的依赖,处理依赖间的冲突,并确保项目中使用的库版本之间的一致性。

  • 多项目构建: Gradle可以轻松地管理和构建多个相关的项目,确保它们之间的依赖和互动得到妥善处理。

  • 插件系统: Gradle具有丰富的插件生态系统,这些插件为特定任务提供额外的功能和工具,如Android应用开发、Web应用部署等。

  • 自定义构建逻辑: 由于Gradle的DSL基于Groovy,开发者可以轻松地编写自定义的构建逻辑,以满足特定的需求或集成其他工具。

  • 性能优化: Gradle具有先进的缓存机制和增量构建能力,这意味着只有当源文件或依赖发生变化时,相关的任务才会被重新执行,大大加速了构建过程。

  • 集成与扩展: Gradle可以与许多现代IDE和CI/CD工具完美集成,如IntelliJ IDEA, Jenkins, Travis CI等,同时也支持通过API来扩展其功能。

总的来说,Gradle不仅仅是一个构建工具,更是一个强大的自动化平台,可以广泛应用于各种软件开发任务和流程中。

三. 依赖管理简介

1)为何依赖管理对于项目至关重要

在现代软件开发中,难得有项目完全独立于外部库或工具。这些外部依赖为我们提供了现成的功能,使得开发更为高效。但同时,如何管理这些依赖也成了一个重要问题。以下是依赖管理对于项目的重要性的几个方面:

  • 版本一致性: 确保项目中使用的所有依赖都是正确和兼容的版本,防止版本冲突导致的运行时错误。

  • 安全性: 有时一些库可能会存在已知的安全问题。有效的依赖管理可以帮助开发者追踪这些问题并及时更新库以解决安全漏洞。

  • 节省时间: 自动化的依赖管理可以减少手工下载和管理库的时间,使得开发者可以专注于编码。

  • 构建的可复制性: 一个好的依赖管理工具可以确保在不同的开发环境中,构建是可复制的,这对于团队协作和持续集成至关重要。

2)如何手动处理依赖和其中的挑战

手动处理依赖通常意味着开发者需要自己下载所需的库,将它们放入项目的某个目录,并确保编译时能找到它们。这种方法存在以下挑战:

  • 版本管理困难: 当有新版本的库发布时,开发者需要手动下载并替换旧版本。这可能导致版本混淆,尤其是当多个库有交叉依赖时。

  • 存储冗余: 如果多个项目使用相同的库,那么这个库的多个副本可能会散落在不同的项目目录中,导致存储浪费。

  • 安全问题: 开发者可能不会经常检查库的更新,这可能使项目长时间使用存在已知安全问题的旧版本。

  • 跨平台问题: 手动管理依赖可能会导致在不同操作系统或环境中出现不一致的构建结果。

因此,尽管手动处理依赖在一些小型或简单的项目中是可行的,但在大多数情况下,使用自动化的依赖管理工具,如Gradle,会更为高效和安全。

四. 编译时依赖

1)定义:什么是编译时依赖

编译时依赖是指在项目的编译阶段所需的依赖。它们对于源代码的编译是必要的,但可能在运行时不需要。这些依赖通常包括用于代码生成、注解处理或提供API定义(例如接口)的库。

2)为何我们需要编译时依赖

  • 代码完整性: 编译时依赖提供了编写源代码时所需的必要类和接口。没有这些依赖,源代码可能无法正确编译。

  • 注解处理: 许多现代框架和库使用注解来简化代码和提供额外的功能。编译时依赖可以包括这些注解处理器,它们在编译过程中运行,生成额外的代码或资源。

  • 类型检查: 编译时依赖还提供了类型信息,帮助编译器在编译过程中进行类型检查,确保代码的类型安全。

3)如何在Gradle中声明编译时依赖

在Gradle中,你可以使用implementationcompile(在旧版本的Gradle中)配置来声明编译时依赖。例如:

dependencies {implementation 'com.some.library:library-name:1.0.0'
}

implementation配置表示该依赖在编译时是必要的,但不需要向消费者(例如其他模块或项目)传递该依赖。这有助于减少传递性依赖,提高构建性能。

4)实际示例

考虑一个常见的Android项目,你可能需要Android的AppCompat库来提供向后兼容的Android功能。在这种情况下,你的build.gradle文件中的依赖声明可能如下:

dependencies {implementation 'androidx.appcompat:appcompat:1.2.0'
}

这表示项目在编译时需要AppCompat库。但是,由于使用了implementation配置,这个库不会传递给依赖你的库或模块的其他项目。

五. 运行时依赖

1)定义:什么是运行时依赖

运行时依赖是指在项目的运行阶段所需的依赖,但在编译时可能并不需要它们。这些依赖在应用或项目执行时必须存在,否则可能会出现类未找到错误或其他运行时异常。

2)为何我们需要运行时依赖

  • 功能实现: 某些库只在运行时提供实际的功能实现。例如,你的代码可能依赖于某个接口(在编译时),但实际的实现可能由一个运行时库提供。

  • 插件和扩展: 在某些情况下,应用程序或框架可能允许通过运行时加载的插件或扩展来增强功能。

  • 动态功能: 一些库可能根据运行时条件提供不同的功能或行为,而这些条件在编译时是不知道的。

3)如何在Gradle中声明运行时依赖

在Gradle中,你可以使用runtimeOnly配置来声明只在运行时需要的依赖,这意味着它们在编译时不会被包括在内。例如:

dependencies {runtimeOnly 'com.some.library:runtime-library:1.0.0'
}

4)实际示例

考虑一个Java web应用,使用了JDBC来连接数据库。虽然在编译时你可能只依赖于JDBC的API(即java.sql包),但在运行时,你需要具体的数据库驱动来实现这些API。假设你正在使用MySQL数据库,那么你的build.gradle文件中的依赖声明可能如下:

dependencies {runtimeOnly 'mysql:mysql-connector-java:8.0.23'
}

这意味着MySQL的JDBC驱动只在运行时需要,而在编译时并不需要它。

六. 编译时与运行时依赖的区别

1)对比二者的主要差异

  • 编译时依赖:

    • 这些依赖在源代码编译阶段是必需的。
    • 对于代码的类型检查和注解处理至关重要。
    • 可能不需要在运行时。
  • 运行时依赖:

    • 这些依赖在项目或应用的执行阶段是必需的。
    • 在编译时可能并不需要。
    • 对于如插件、动态功能实现等运行时行为至关重要。

2)解释为何某些库可能仅在编译时需要,而其他库可能在运行时需要

某些库在编译时提供必要的类型信息、注解处理功能或其他编译时功能,但在运行时不再使用,因此只在编译时需要它们。这种情况下,这些库的代码不会被包括在最终的运行时类路径中。

而其他库可能提供实际的功能实现,这些功能只在应用运行时执行时才需要。例如,一个应用可能在编译时依赖于某个通用接口,而在运行时依赖于该接口的具体实现,这个实现是由一个单独的库提供的。

3)举例说明这些差异

示例 1: 注解处理器
很多现代Java库使用注解处理器在编译时生成代码。这些处理器在编译阶段是必要的,但在运行时并不需要它们,因为它们的工作已经完成了。例如,Lombok库就是这样的一个库,它在编译时生成getter和setter方法,但在运行时并不需要Lombok库。

示例 2: JDBC驱动
如前面提到的,一个应用可能在编译时只依赖于JDBC API,这是Java的标准部分。但在运行时,应用需要具体的数据库驱动(例如MySQL或PostgreSQL驱动)来实际连接到数据库。这个驱动在编译时并不需要,但在运行时是必需的。

这两个示例突出了编译时和运行时依赖之间的主要区别,以及为什么在某些情况下,某些库只在一个阶段需要,而在另一个阶段不需要。

七. 常见问题和陷阱

1)讨论关于编译时和运行时依赖的常见误区

  • “编译成功即可运行成功”误区:仅因为代码成功编译并不意味着它在运行时不会遇到问题。有可能缺少运行时所需的依赖,或者使用了与运行环境不兼容的库版本。

  • 过度依赖:认为所有编译时的依赖都必须包含在运行时类路径中。这可能会导致不必要的库被包括,从而增加了部署包的大小。

  • 版本冲突误区:不同的库可能依赖于相同库的不同版本。在编译时,这可能不会引起问题,但在运行时可能会导致类版本错误或其他相似的问题。

  • 忽视间接依赖:认为只有直接在项目中声明的依赖是重要的,而忽视了这些依赖所引入的其他间接依赖。这可能导致运行时错误,因为缺少了某些必要的库。

2)如何避免这些问题

  • 持续集成和自动测试:使用CI/CD工具确保每次代码更改后都会进行编译和运行测试。这可以及时发现和修复潜在的运行时问题。

  • 清晰地分隔编译时和运行时依赖:在项目配置中明确区分这两种依赖,确保只有真正需要的库被包含在运行时类路径中。

  • 使用依赖管理工具:像Gradle和Maven这样的工具可以自动处理版本冲突和间接依赖的问题。它们可以帮助你确定哪些库版本是兼容的,并确保所有必要的库都被正确地包含。

  • 定期审核依赖:定期查看项目的依赖列表,确保没有不再使用的库,并验证当前使用的库版本是否是最新的和最安全的。

  • 学习和理解你的依赖:尝试深入了解你的项目所依赖的库,这可以帮助你更好地理解这些库的工作原理,从而避免一些常见的陷阱。

八. 最佳实践

1)如何最优化地管理Gradle的编译时和运行时依赖

  • 明确声明依赖:总是明确声明项目中直接使用的所有依赖,而不是依赖间接引入的库。

  • 使用implementationapi配置:在build.gradle文件中, 使用implementation为编译时依赖和api为运行时依赖。这确保了只有真正需要的依赖会被包括在最终的产出中。

  • 避免使用compile配置:从Gradle 3.0开始,compile已经被废弃。应该使用implementationapi来替代。

  • 定期检查依赖更新:使用像Gradle Versions Plugin这样的工具,定期检查是否有依赖库的新版本,并在适当的时候更新它们。

  • 管理依赖版本:在build.gradle中使用变量来管理依赖的版本号,这样当需要更新多个相关依赖的版本时,只需更改一次。

2)实际的例子和提示

  • 声明编译时依赖

    dependencies {implementation 'com.example:library:1.0.0'
    }
    
  • 声明运行时依赖

    dependencies {api 'com.example:runtime-library:2.0.0'
    }
    
  • 使用变量管理版本

    ext {libraryVersion = '1.0.0'
    }dependencies {implementation "com.example:library:${libraryVersion}"
    }
    
  • 检查过时的依赖:使用./gradlew dependencyUpdates(需要Gradle Versions Plugin)来查看所有过时的依赖。

  • 避免过度依赖:如果你注意到有一些库在运行时没有被使用,考虑从依赖中删除它们或将它们更改为编译时依赖。

九. 总结

1)编译时和运行时依赖的重要性和区别

编译时和运行时依赖在软件开发的各个阶段都起到了核心的作用。编译时依赖主要涉及到在代码编译阶段所需的库和资源。这些依赖项为我们提供了必要的APIs和工具,以确保代码在编译时没有错误。而运行时依赖则是当应用运行时所需的库。它们确保在实际运行应用程序时,所有的功能都能够正确执行。

二者之间的关键区别在于它们的使用时机:编译时依赖在代码编译阶段是必要的,而运行时依赖则是在代码执行时是必要的。理解这些区别并正确管理这两种依赖是至关重要的,因为错误的依赖管理可能导致编译失败或运行时错误。

2)为何好的依赖管理对于项目成功至关重要

良好的依赖管理是软件项目成功的关键。首先,它确保我们的代码在所有环境中都能够一致和可靠地执行。其次,通过减少不必要的或冗余的依赖,它可以帮助我们减少应用的大小,提高加载速度,并减少潜在的安全风险。

更重要的是,有效的依赖管理可以帮助团队更快速地迭代和交付高质量的软件。当我们知道我们的代码依赖于哪些库,以及这些库的版本时,我们就可以更容易地跟踪和修复bugs,更新库版本,或进行其他必要的维护工作。

因此,无论是个人开发者还是大型团队,都应该投资时间和精力来确保他们的依赖管理策略是最优的,从而确保他们的项目能够成功。

十. 参考资料

  • Gradle官方文档: https://docs.gradle.org
  • Android开发者官方文档:Gradle概述: https://developer.android.com/studio/build
  • Smith, J. (2022). “Understanding Gradle Dependency Management”. O’Reilly Media.
  • Lee, K. & Park, H. (2021). “Gradle in Action: Effective Dependency Management”. Springer.

十一. 互动/评论区

亲爱的读者,感谢您阅读这篇文章!我们非常期待您的反馈。您在Gradle依赖管理方面有什么经验或建议?您是否遇到过任何与本文相关的问题或挑战?请在下方留言与我们分享您的见解和疑问。您的反馈将为我们所有人带来巨大的价值!

在这里插入图片描述

原创声明

======= ·

  • 原创作者: 猫头虎

作者wx: [ libin9iOak ]

学习复习

本文为原创文章,版权归作者所有。未经许可,禁止转载、复制或引用。

作者保证信息真实可靠,但不对准确性和完整性承担责任

未经许可,禁止商业用途。

如有疑问或建议,请联系作者。

感谢您的支持与尊重。

点击下方名片,加入IT技术核心学习团队。一起探索科技的未来,共同成长。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode】《LeetCode 101》第十一章:妙用数据结构

文章目录 11.1 C STL11.2 数组448. 找到所有数组中消失的数字(简单)48. 旋转图像(中等)74. 搜索二维矩阵(中等)240. 搜索二维矩阵 II(中等)769. 最多能完成排序的块(中等…

ROSpider机器人评测报告

ROSpider机器人评测报告 最近入手了一款ROSpider六足仿生机器人,ROSpider是一款基于ROS 操作系统开发的智能视觉六足机器人。 外观 外观上ROSpider六足机器人如同名字一样有六只机械腿,整体来看像一只六腿的蜘蛛。腿上的关节处用了明亮的橙黄色很是显…

Redis使用Lua脚本和Redisson来保证库存扣减中的原子性和一致性

文章目录 前言1.使用SpringBoot Redis 原生实现方式2.使用redisson方式实现3. 使用RedisLua脚本实现3.1 lua脚本代码逻辑 3.2 与SpringBoot集成 4. Lua脚本方式和Redisson的方式对比5. 源码地址6. Redis从入门到精通系列文章7. 参考文档 前言 背景:最近有社群技术交…

C++——函数重载及底层原理

函数重载的定义 函数重载: 是函数的一种特殊情况,C允许在同一作用域重声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数或者类型,类型的顺序)不同,常用来处理实现功能类似数据结构…

春秋云镜 CVE-2021-41947

春秋云镜 CVE-2021-41947 Subrion CMS v4.2.1 存在sql注入 靶标介绍 Subrion CMS v4.2.1 存在sql注入。 启动场景 漏洞利用 exp http://localhost/panel/visual-mode.json?getaccess&typeblocks UNION ALL SELECT username, password FROM sbr421_members -- -&o…

【需求输出】流程图输出

文章目录 1、什么是流程图2、绘制流程图的工具和基本要素3、流程图的分类和应用场景4、如何根据具体场景输出流程图 1、什么是流程图 2、绘制流程图的工具和基本要素 3、流程图的分类和应用场景 4、如何根据具体场景输出流程图

Dubbo1-架构的演变

分布式系统上的相关概念 项目:传统项目、互联网项目 传统项目: 一般为公司内部使用,或者小群体小范围的使用,一般不要求性能,美观,并发等 互联网项目的特点: 1.用户多 2.流量大,并…

用python来爬取某鱼的商品信息(2/2)

目录 上一篇文章 本章内容 设置浏览器为运行结束后不关闭(可选) 定位到搜索框的xpath地址 执行动作 获取cookie 保存为json文件 修改cookie的sameSite值并且导入cookie 导入cookie(出错) 导入cookie(修改后&…

Android Ble蓝牙App(五)数据操作

Ble蓝牙App(五)数据操作 前言正文一、操作内容处理二、读取数据① 概念② 实操 三、写入数据① 概念② 实操 四、打开通知一、概念二、实操三、收到数据 五、源码 前言 关于低功耗蓝牙的服务、特性、属性、描述符都已经讲清楚了,而下面就是使…

电脑系统重装日记

重装原因 电脑C盘几乎爆炸故重装系统一清二白 此片原因 记录重装过程,强调一些要注意的点,以防日后重装。 重装过程 1.清空电脑文件后重启,电脑冒蓝光,一直蓝屏反复重启,故只能重装系统以解难题。 2.准备一个U盘&…

设计HTML5文档结构

定义清晰、一致的文档结构不仅方便后期维护和拓展,同时也大大降低了CSS和JavaScript的应用难度。为了提高搜索引擎的检索率,适应智能化处理,设计符合语义的结构显得很重要。 1、头部结构 在HTML文档的头部区域,存储着各种网页元…

Python Opencv实践 - 图像属性相关

import numpy as np import cv2 as cv import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) plt.imshow(img[:,:,::-1])#像素操作 pixel img[320,370] print(pixel)#只获取蓝色通道的值 pixel_blue img[320,370,0]…

【Hystrix技术指南】(7)故障切换的运作流程原理分析(含源码)

背景介绍 目前对于一些非核心操作,如增减库存后保存操作日志发送异步消息时(具体业务流程),一旦出现MQ服务异常时,会导致接口响应超时,因此可以考虑对非核心操作引入服务降级、服务隔离。 Hystrix说明 官方…

Grounding DINO:根据文字提示检测任意目标

文章目录 1. 背景介绍2. 方法创新2.1 Feature Extraction and Enhancer2.2 Language-Guided Query Selection2.3 Cross-Modality Decoder2.4 Sub-Sentence Level Text Feature2.5 Loss Function3. 实验结果3.1 Zero-Shot Transfer of Grounding DINO3.2 Referring Object Detec…

设备管理系统能起到什么作用?

在现代工业运营中,设备的高效管理和维护对于保障生产稳定运行和提升企业竞争力至关重要。而设备管理系统作为一种关键工具,能够极大地提高企业的生产效率和设备维护的准确性。本文将深入探讨设备管理系统的作用,以PreMaint设备数字化平台为例…

ES踩坑记录之UNASSIGNED分片无法恢复

问题背景 换节点 我们线上有一套ES集群,三台机器,共运行了6个节点。一直在线上跑了几个月也一直没出什么问题。然而好巧不巧,就在昨天,集群中的3号节点磁盘出现故障,导致机器直接瘫痪。本来大家觉得问题不大&#xf…

HTML和JavaScript实现一个简单的计算器

使用HTML和JavaScript实现一个简单的计算器。 一、绘制键盘 <!DOCTYPE html> <html> <head><title>Simple Calculator</title><style>.calculator {display: grid;grid-template-columns: repeat(4, 1fr);grid-gap: 5px;padding: 10px;}.…

【elementUi】绘制自定义表格、绘制曲线表格

要求绘制下图系列表格&#xff1a; 实现步骤: 1.绘制树&#xff0c;实现树勾选字段—>表格绘制字段 逻辑&#xff1a; 树&#xff1a;check-change“treeChart.handleCheckChange” 绑定点击选择事件&#xff0c;改变data.column3数据项&#xff1b;表格:columns"data…

基于 Nginx All In One 的 Outline Wiki 部署方法

1. Outline 简介 官网&#xff1a;https://www.getoutline.com/ Outline 是一个开源的知识库和团队协作工具&#x1f9e0;&#xff0c;旨在帮助团队共享、组织和协作文档&#x1f4dd;。它提供了一个简洁的界面&#xff0c;使用户能够轻松创建、编辑和查看文档。 以下是 Out…

Ajax 笔记(四)—— Ajax 进阶

笔记目录 4. Ajax 进阶4.1 同步代码和异步代码4.2 回调函数地狱4.2.1 解决方法一&#xff1a;Promise 链式调用4.2.2 解决方法二&#xff1a;async 函数和 await 4.3 Promise.all 静态方法4.4 事件循环4.4.1 事件循环4.4.2 宏任务与微任务 4.5 案例4.5.1 案例一-商品分类4.5.2 …