搜索
首页web前端js教程Async/Await 与 Promises:JavaScript 初学者简单指南

Async/Await vs Promises: A Simple Guide for JavaScript Beginners

您是否曾经感觉自己在咖啡店排队等候 JavaScript 来取拿铁咖啡?异步编程常常给人这样的感觉——同时处理多个订单可能会让您陷入等待。幸运的是,Promisesasync/await 等工具可确保流程保持平稳高效,让您的代码继续运行而不会出现延迟。

在本指南中,我们将详细介绍 Promise 的工作原理、引入 async/await 的原因,以及它如何简化异步代码的编写。无论您是试图掌握这些概念的初学者,还是想清楚何时使用每种方法,本文都将帮助您掌握基础知识。

什么是承诺?

Promise 是 JavaScript 中处理异步操作的基本概念。从本质上讲,Promise 代表了现在稍后永远可用的值。将其视为包裹的追踪号码:虽然您还没有收到包裹,但追踪号码让您确信包裹正在运送途中(或者让您知道是否出现问题)。

基于“现在、以后或永远”的叙述,Promise 实际上在以下三种状态之一中运行:

  • 待处理:异步操作尚未完成。
  • 已完成:操作已成功完成,Promise 现在保存结果。
  • 已拒绝:出了点问题,Promise 提供了一个错误。

创建和使用 Promise 涉及一个简单的 API。以下是定义 Promise 的方法:

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const data = { id: 1, name: "JavaScript Basics" };
    resolve(data); // Simulates a successful operation
    // reject("Error: Unable to fetch data"); // Simulates a failure
  }, 1000);
});

要处理结果,您可以将 .then()、.catch() 和 .finally() 方法链接到 Promise 对象:

fetchData
  .then((data) => {
    console.log("Data received:", data);
  })
  .catch((error) => {
    console.error(error);
  })
  .finally(() => {
    console.log("Operation complete.");
  });

当 Promise 解析成功时执行 then() 方法中的回调。 .catch() 方法中的回调在 Promise 解析失败时执行,finally() 方法中的回调在 Promise 解析后执行,无论解析结果如何。

Promise 的好处

Promise 为深层嵌套的回调(通常称为“回调地狱”)提供了一种更干净的替代方案。 Promise 允许链接,而不是堆叠回调,从而使操作流程更易于遵循:

doTask1()
  .then((result1) => doTask2(result1))
  .then((result2) => doTask3(result2))
  .catch((error) => console.error("An error occurred:", error));

如果使用传统回调编写相同的代码,它会是什么样子:

doTask1((error1, result1) => {
  if (error1) {
    console.error("An error occurred:", error1);
    return;
  }
  doTask2(result1, (error2, result2) => {
    if (error2) {
      console.error("An error occurred:", error2);
      return;
    }
    doTask3(result2, (error3, result3) => {
      if (error3) {
        console.error("An error occurred:", error3);
        return;
      }
      console.log("Final result:", result3);
    });
  });
});

令人困惑,不是吗?这就是为什么 Promise 在引入时就改变了 JavaScript 编码标准。

Promise 的缺点

虽然 Promises 极大地改进了传统的回调函数,但它们也面临着自己独特的挑战。尽管有这些好处,但它们在复杂的场景中可能会变得笨拙,导致代码冗长和调试困难。

即使使用 .then() 链接,Promise 在处理多个异步操作时也会导致代码混乱。例如,使用 .then() 块管理顺序操作和使用 .catch() 进行错误处理可能会让人感觉重复且难以理解。

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const data = { id: 1, name: "JavaScript Basics" };
    resolve(data); // Simulates a successful operation
    // reject("Error: Unable to fetch data"); // Simulates a failure
  }, 1000);
});

虽然比嵌套回调更清晰,但链接语法仍然很冗长,特别是在需要详细的自定义错误处理逻辑时。此外,忘记在链的末尾添加 .catch() 可能会导致静默失败,从而使调试变得棘手。

此外,Promise 中的堆栈跟踪不如同步代码中的堆栈跟踪那么直观。发生错误时,堆栈跟踪可能无法清楚地指示异步流程中问题的根源。

最后,虽然 Promise 有助于减少回调地狱,但当任务相互依赖时,它们仍然会导致复杂性。嵌套的 .then() 块可以在某些用例中重新出现,带回一些它们本来要解决的可读性挑战。

输入异步/等待

随着 ES2017 (ES8) 中 async/await 的引入,JavaScript 中的异步编程取得了巨大的飞跃。 async/await 构建在 Promises 之上,允许开发人员编写外观和行为更像同步代码的异步代码。这使其成为真正的游戏规则改变者,可以提高可读性、简化错误处理并减少冗长。

什么是异步/等待?

Async/await 是一种旨在使异步代码更易于理解和维护的语法。

async 关键字用于声明一个始终返回 Promise 的函数。在此函数中,await 关键字暂停执行,直到 Promise 得到解决或拒绝。这会产生线性且直观的流程,即使对于复杂的异步操作也是如此。

下面是 async/await 如何简化您在上面看到的相同代码示例的示例:

fetchData
  .then((data) => {
    console.log("Data received:", data);
  })
  .catch((error) => {
    console.error(error);
  })
  .finally(() => {
    console.log("Operation complete.");
  });

Async/await 消除了对 .then() 链的需要,允许代码按顺序流动。这使得遵循逻辑变得更容易,特别是对于需要依次执行的任务。

对于 Promise,必须使用 .catch() 在链的每个级别捕获错误。另一方面,Async/await 使用 try/catch 整合错误处理,减少重复并提高清晰度。

Async/await 产生比 Promise 更直观的堆栈跟踪。当发生错误时,跟踪会反映实际的函数调用层次结构,从而减少调试的麻烦。总的来说,async/await 感觉更“自然”,因为它与同步代码的编写方式一致。

比较 Promise 和 async/await

正如您已经看到的,Async/await 在可读性方面表现出色,尤其是对于顺序操作。 Promise 及其 .then() 和 .catch() 链接很快就会变得冗长或复杂。相比之下,异步/等待代码更容易理解,因为它模仿同步结构。

灵活性

Promise 仍然有一席之地,特别是对于并发任务。 Promise.all() 和 Promise.race() 等方法对于并行运行多个异步操作更有效。 Async/await 也可以处理这种情况,但需要额外的逻辑才能达到相同的结果。

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const data = { id: 1, name: "JavaScript Basics" };
    resolve(data); // Simulates a successful operation
    // reject("Error: Unable to fetch data"); // Simulates a failure
  }, 1000);
});

错误处理

虽然使用单个 .catch() 进行集中式错误处理对于 Promises 的线性链效果很好,但建议对跨链的不同错误类型使用分布式 .catch 调用,以获得最佳可读性。

另一方面,try/catch 块为处理错误提供了更自然的结构,特别是在处理顺序任务时。

表现

就性能而言,async/await 本质上等同于 Promises,因为它是建立在 Promises 之上的。然而,对于需要并发的任务,Promise.all() 可以更高效,因为它允许多个 Promise 并行执行,如果任何 Promise 拒绝,则快速失败。

何时使用哪个

如果您的任务涉及大量并发操作,例如同时从多个 API 获取数据,Promise 很可能是更好的选择。如果您的异步代码不涉及大量链接,那么 Promise 也非常适合这种情况,因为它很简单。

另一方面,async/await 在需要顺序执行大量任务或优先考虑可读性和可维护性的情况下表现出色。例如,如果您有一系列相关操作,例如获取数据、转换数据和保存数据,则 async/await 提供干净且同步的结构。这使得跟踪操作流程变得更加容易,并通过 try/catch 块简化了集中式错误处理。 Async/await 对于初学者或优先考虑可读代码的团队特别有用。

结论

JavaScript 提供了两个强大的工具来管理异步操作:Promises 和 async/await。 Promise 彻底改变了开发人员处理异步任务的方式,解决了回调地狱和启用链接等问题。 Async/await 建立在 Promises 的基础上,提供了更清晰的语法,感觉更自然和直观,特别是对于顺序任务。

既然您已经探索了这两种方法,您就可以选择最适合您需求的一种了。尝试将基于 Promise 的函数转换为 async/await 并观察可读性的差异!

有关更多信息,请查看 MDN Promise 文档或尝试交互式编码沙箱!

以上是Async/Await 与 Promises:JavaScript 初学者简单指南的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
JavaScript数据类型:浏览器和nodejs之间是否有区别?JavaScript数据类型:浏览器和nodejs之间是否有区别?May 14, 2025 am 12:15 AM

JavaScript核心数据类型在浏览器和Node.js中一致,但处理方式和额外类型有所不同。1)全局对象在浏览器中为window,在Node.js中为global。2)Node.js独有Buffer对象,用于处理二进制数据。3)性能和时间处理在两者间也有差异,需根据环境调整代码。

JavaScript评论:使用//和 / * * / * / * /JavaScript评论:使用//和 / * * / * / * /May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript:开发人员的比较分析Python vs. JavaScript:开发人员的比较分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要区别在于类型系统和应用场景。1.Python使用动态类型,适合科学计算和数据分析。2.JavaScript采用弱类型,广泛用于前端和全栈开发。两者在异步编程和性能优化上各有优势,选择时应根据项目需求决定。

Python vs. JavaScript:选择合适的工具Python vs. JavaScript:选择合适的工具May 08, 2025 am 12:10 AM

选择Python还是JavaScript取决于项目类型:1)数据科学和自动化任务选择Python;2)前端和全栈开发选择JavaScript。Python因其在数据处理和自动化方面的强大库而备受青睐,而JavaScript则因其在网页交互和全栈开发中的优势而不可或缺。

Python和JavaScript:了解每个的优势Python和JavaScript:了解每个的优势May 06, 2025 am 12:15 AM

Python和JavaScript各有优势,选择取决于项目需求和个人偏好。1.Python易学,语法简洁,适用于数据科学和后端开发,但执行速度较慢。2.JavaScript在前端开发中无处不在,异步编程能力强,Node.js使其适用于全栈开发,但语法可能复杂且易出错。

JavaScript的核心:它是在C还是C上构建的?JavaScript的核心:它是在C还是C上构建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; saninterpretedlanguagethatrunsonenginesoftenwritteninc.1)javascriptwasdesignedAsalightweight,解释edganguageforwebbrowsers.2)Enginesevolvedfromsimpleterterterpretpreterterterpretertestojitcompilerers,典型地提示。

JavaScript应用程序:从前端到后端JavaScript应用程序:从前端到后端May 04, 2025 am 12:12 AM

JavaScript可用于前端和后端开发。前端通过DOM操作增强用户体验,后端通过Node.js处理服务器任务。1.前端示例:改变网页文本内容。2.后端示例:创建Node.js服务器。

Python vs. JavaScript:您应该学到哪种语言?Python vs. JavaScript:您应该学到哪种语言?May 03, 2025 am 12:10 AM

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器