当前位置:首页 > 文章列表 > 文章 > 前端 > Async/Await 与 Promises:JavaScript 初学者简单指南

Async/Await 与 Promises:JavaScript 初学者简单指南

来源:dev.to 2024-12-19 14:25:02 0浏览 收藏

本篇文章给大家分享《Async/Await 与 Promises:JavaScript 初学者简单指南》,覆盖了文章的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握它。

Async/Await 与 Promises:JavaScript 初学者简单指南

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

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

什么是承诺?

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

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

  • pending:异步操作尚未完成。
  • 已完成:操作已成功完成,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() 进行错误处理可能会让人感觉重复且难以理解。

dotask1()
  .then((result1) => dotask2(result1))
  .catch(task1error, (error) => console.error("an error occurred in task 1:", error));

  .then((result2) => dotask3(result2))
  .catch(task2error, (error) => console.error("an error occurred in task 2:", error));

  .catch((error) => console.error("an error occurred in the chain:", error));

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

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

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

输入异步/等待

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

什么是异步/等待?

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

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

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

async function executetasks() {
  try {
    const result1 = await dotask1();
    const result2 = await dotask2(result1);
    const result3 = await dotask3(result2);
    console.log("all tasks completed successfully:", result3);
  } catch (error) {
    if (error instanceof task1error) {
      console.error("an error occurred in task 1:", error);
    } else if (error instanceof task2error) {
      console.error("an error occurred in task 2:", error);
    } else {
      console.error("an error occurred in the chain:", error);
    }
  }
}

executetasks();

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 也可以处理这种情况,但需要额外的逻辑才能达到相同的结果。

// A Promise.all() example
Promise.all([task1(), task2(), task3()])
  .then((results) => console.log("All tasks completed:", results))
  .catch((error) => console.error("An error occurred:", error));

错误处理

虽然使用单个 .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 初学者简单指南》文章吧,也可关注golang学习网公众号了解相关技术文章。

版本声明
本文转载于:dev.to 如有侵犯,请联系study_golang@163.com删除
win11改mac地址的方法win11改mac地址的方法
上一篇
win11改mac地址的方法
win10系统屏幕保护时间太短怎么办 win10系统调整屏幕保护时间的方法
下一篇
win10系统屏幕保护时间太短怎么办 win10系统调整屏幕保护时间的方法
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • Vozo AI:超真实AI视频换脸工具,提升创意内容制作
    Vozo AI
    探索Vozo AI,一款功能强大的在线AI视频换脸工具,支持跨性别、年龄和肤色换脸,适用于广告本地化、电影制作和创意内容创作,提升您的视频制作效率和效果。
    2次使用
  • AIGAZOU:免费AI图像生成工具,简洁高效,支持中文
    AIGAZOU-AI图像生成
    AIGAZOU是一款先进的免费AI图像生成工具,无需登录即可使用,支持中文提示词,生成高清图像。适用于设计、内容创作、商业和艺术领域,提供自动提示词、专家模式等多种功能。
    2次使用
  • 笔灵AI生成答辩PPT:高效制作学术与职场PPT的利器
    笔灵AI生成答辩PPT
    探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
    30次使用
  • 知网AIGC检测服务系统:精准识别学术文本中的AI生成内容
    知网AIGC检测服务系统
    知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
    45次使用
  • AIGC检测服务:AIbiye助力确保论文原创性
    AIGC检测-Aibiye
    AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
    40次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码