”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > JavaScript Promise:您需要了解的基础知识

JavaScript Promise:您需要了解的基础知识

发布于2024-11-08
浏览:965

JavaScript Promises: The Basics You Need to Know

介绍

JavaScript 是一种单线程编程语言,这意味着它一次只能运行一个任务。对于诸如获取数据或设置计时器之类的异步操作来说,这变得很棘手,这可能会阻止执行流程并减慢应用程序的速度。

为了在不冻结线程的情况下处理这些异步任务,我们遇到了Promise——一个简化异步编程的强大工具。使用 Promises,您可以更有效地管理长时间运行的任务,编写更干净、更具可读性的代码,并避免可怕的“回调地狱。

在本文中,我的目标是让您熟悉 Promises 是什么、它们如何工作以及它们如何简化异步编程。

什么是承诺?

想象一下您正在一家餐厅点餐。下订单后,您无需在厨房等待食物准备好。相反,您可以在厨房在后台准备餐点的同时继续交谈或享受氛围。餐厅承诺一旦食物准备好,就会为您提供食物。您可以相信这个承诺,因为最终会发生以下两种情况之一:您的餐食将到达(已完成),或者厨房将通知您他们无法完成订单(已拒绝).

在 JavaScript 中,Promises 的工作方式类似。当您要求 JavaScript 执行一些需要时间的操作(例如从服务器获取数据)时,它会返回 Promise。这个 Promise 不会立即给你结果。相反,它会告诉您,“工作完成后我会回复您。”在此期间,其余代码将继续运行。任务完成后,Promise 为:

  • 已完成(任务成功),或
  • 拒绝(任务失败),您可以进行相应处理。

Promise 在 JavaScript 中如何工作

A Promise 代表一个可能现在、将来或永远不可用的值。它有三种状态:

  • 待处理:任务仍在进行中,最终结果(完成或拒绝)尚未确定。
  • 已完成:任务成功完成,结果可见。
  • 已拒绝:任务失败,有错误可处理

1. 创造一个承诺

要创建 Promise,请使用 Promise 构造函数,该构造函数接受一个具有两个参数的函数(称为执行器):resolve 和reject。当Promise被满足时,resolve函数被调用,而当被拒绝时,reject函数被调用。

const myPromise = new Promise((resolve, reject) => {
  // Simulating an asynchronous task (e.g., fetching data)
  const success = true; // Simulate success or failure

  if (success) {
    resolve("Operation completed successfully!"); // Fulfill the promise
  } else {
    reject("Operation failed."); // Reject the promise
  }
});

2. 解决和拒绝承诺

一旦创建了Promise,您可以通过调用resolve或reject来决定其结果:

  • resolve(value):当异步操作成功完成时调用此函数。它将一个值传递给等待 Promise 履行的处理程序。
  • reject(error):当操作失败时调用该函数。它将错误消息传递给等待 Promise 被拒绝的处理程序。

3. 消费承诺

创建了 Promise 后,下一步就是使用它。 JavaScript 提供了几种处理 Promise 结果的方法:.then()、.catch() 和 .finally()。这些方法中的每一个都有特定的目的,并允许您有效地管理异步操作的结果。

  • 使用 .then() 处理已解决的 Promise:.then() 方法用于指定当 Promise 被履行时应该发生什么。它需要两个可选参数:一个用于解析值的回调,另一个用于处理拒绝。
const fetchData = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("Data fetched successfully!");
    }, 1000);
  });
};

fetchData()
  .then(result => {
    console.log(result); // Logs: Data fetched successfully!
  });
  • 使用 .catch() 处理拒绝:.catch() 方法专门用于处理 Promise 执行期间发生的错误。这使其成为处理拒绝的干净方法。
const fetchWithError = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Error fetching data."); // Simulating an error
    }, 1000);
  });
};

fetchWithError()
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.error(error); // Logs: Error fetching data.
  });
  • 使用 .finally() 进行最终或清理操作:.finally() 方法允许您在 Promise 解决后执行代码,无论它是被履行还是被拒绝。这对于应在成功和失败场景中运行的清理操作或任务非常有用。
fetchData()
  .then(result => {
    console.log(result); // Logs: Data fetched successfully!
  })
  .catch(error => {
    console.error(error); // Handle error
  })
  .finally(() => {
    console.log("Promise has settled."); // Logs after either success or failure
  });

简而言之:

  • then():使用此方法处理 Promise 的解析值。
  • catch():使用此方法来处理 Promise 被拒绝时的错误。
  • finally():此方法在 Promise 解决后运行代码,无论结果如何,允许清理或最终操作。

4. 承诺链

Promises 最强大的功能之一是它们能够链接在一起,允许您按顺序执行多个异步操作。这意味着每个操作在执行之前都要等待前一个操作完成,这在任务相互依赖时特别有用。

我们看下面的例子:

const fetchUserData = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ userId: 1, username: "JohnDoe" });
    }, 1000);
  });
};

const fetchPosts = (userId) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(["Post 1", "Post 2", "Post 3"]); // Simulated posts
    }, 1000);
  });
};

// Chaining Promises
fetchUserData()
  .then(user => {
    console.log("User fetched:", user);
    return fetchPosts(user.userId); // Pass userId to the next promise
  })
  .then(posts => {
    console.log("Posts fetched:", posts);
  })
  .catch(error => {
    console.error("Error:", error);
  });

在此示例中,fetchUserData 函数返回一个用用户信息解析的 Promise。然后将解析后的值传递给 fetchPosts 函数,该函数返回另一个 Promise。如果这些 Promise 中的任何一个被拒绝,则错误将在最终的 .catch() 方法中捕获,从而允许在整个链中进行有效的错误处理。

结论

总之,Promise 是现代 JavaScript 的重要组成部分,使开发人员能够以更加结构化和高效的方式处理异步操作。通过使用 Promise,您可以:

  • 简化异步任务的管理,避免回调地狱。
  • 链接多个异步操作以保持清晰的执行流程。
  • 通过统一的方法有效处理错误。

当您在自己的项目中实现 Promise 时,您会发现它们不仅提高了代码的可读性,而且还通过保持应用程序的响应能力来增强整体用户体验。我希望这段 JavaScript 基本概念之旅能够为开发人员提供有价值的见解。快乐编码!

版本声明 本文转载于:https://dev.to/dev-v/javascript-promises-the-basics-you-need-to-know-8k2?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 了解 DOM 事件
    了解 DOM 事件
    DOM 事件使网页具有交互性。使用 DOM 事件可以实现页面点击或表单提交,它可以让开发人员创建引人入胜的用户体验。 DOM 事件的一些示例包括用户单击鼠标时、加载网页时、加载图像时、提交 HTML 表单时以及用户按下某个键时。 在本文中,我们将简化 DOM 事件中的关键概念并探讨如何处理它们。 ...
    编程 发布于2024-11-08
  • 为什么 PHP 中的“+”运算符不连接数组?
    为什么 PHP 中的“+”运算符不连接数组?
    理解 PHP 中的数组串联尝试使用 ' ' 运算符组合两个数组时,用户可能会遇到意外结果。这就是为什么以下代码没有按预期连接数组的原因:$array = array('Item 1'); $array = array('Item 2'); var_dump($array);此代码将...
    编程 发布于2024-11-08
  • 为什么 IE 日期构造函数与 Chrome 和 Firefox 日期处理不同?
    为什么 IE 日期构造函数与 Chrome 和 Firefox 日期处理不同?
    IE 日期构造函数问题:NaN 与其他浏览器中的功能在涉及 JavaScript 日历开发的项目中,日期处理中出现了差异Internet Explorer (IE) 以及 Firefox 和 Chrome 等浏览器。具体来说,IE 的日期函数产生 NaN(非数字)值,而它们在其他浏览器中正常运行。经...
    编程 发布于2024-11-08
  • 如何使用正则表达式删除 PHP 字符串中的特定特殊字符,同时保留其他字符?
    如何使用正则表达式删除 PHP 字符串中的特定特殊字符,同时保留其他字符?
    PHP:从字符串中删除特殊字符在 PHP 中,从字符串中删除特殊字符可能是一项常见任务,尤其是在处理用户输入或外部数据时。面临的挑战是删除所有不需要的字符,而不改变标点符号或空格等基本字符。为了解决这个问题,通常使用正则表达式。但是,当尝试删除特定特殊字符并保留其他特殊字符时,需要对表达式进行修改。...
    编程 发布于2024-11-08
  • 如何保证PHP中不同平台的换行符一致?
    如何保证PHP中不同平台的换行符一致?
    使用 PHP 在多个平台中回显换行符在 PHP 中回显换行符时,字符 \n 和 \r 起着至关重要的作用。它们分别代表换行符和回车符。两者之间的区别在于操作系统兼容性。\n 与 \r\n (换行符) :在基于 Unix 的系统(如 Linux 和 macOS)中用于标记行尾。\r(回车回车):在Wi...
    编程 发布于2024-11-08
  • 您可以使用 Matplotlib 根据 Pandas 中的特定列值绘制彩色散点图吗?
    您可以使用 Matplotlib 根据 Pandas 中的特定列值绘制彩色散点图吗?
    使用 Pandas 和 Matplotlib 按列值对散点图着色Matplotlib 是一个流行的 Python 库,用于在Python。本文探讨使用 Matplotlib 根据 Pandas DataFrame 特定列中的值对散​​点图进行着色。导入和数据首先,我们导入必要的库,包括 Matplo...
    编程 发布于2024-11-08
  • 使用 Quarkus 和 GraalVM 本机映像增强 Java 微服务
    使用 Quarkus 和 GraalVM 本机映像增强 Java 微服务
    在现代软件开发的动态格局中,微服务已成为最受欢迎的架构方法。虽然这种方法提供了许多优点,但它也并非没有挑战。传统的基于 JVM 的服务经常会出现内存占用过大、启动时间过长以及 CPU 使用率过高等问题。这些挑战不仅影响技术方面,还会产生财务影响,从而显着影响运行和维护软件解决方案的总体成本。 ...
    编程 发布于2024-11-08
  • 如何确定 C/C++ 编译器中的行号?
    如何确定 C/C++ 编译器中的行号?
    在 C/C 编译器中获取行号调试 C/C 代码时,确定某个行所在的行号非常有用发生错误。常见的解决方案是手动向代码添加行号,但更有效的方法是使用内置预处理器宏。行号的标准预处理器宏C/C 标准定义了两个预处理器宏:__LINE__:提供当前行号file.__FILE__: 给出当前文件名。用法示例打...
    编程 发布于2024-11-08
  • 如何用PHP和jQuery实现高效的多文件上传?
    如何用PHP和jQuery实现高效的多文件上传?
    使用 PHP 和 jQuery 有效上传多个文件在使用 PHP 时,您可能会遇到需要同时上传多个文件的情况。让我们探讨如何使用 PHP 和 jQuery 实现多个文件上传功能。PHP 和 HTML 配置在您的 HTML 表单中,您将有一个输入字段,其中包含多个属性设置允许多项选择。 JavaScri...
    编程 发布于2024-11-08
  • 如何在 JavaScript 中有效生成不重复随机数?
    如何在 JavaScript 中有效生成不重复随机数?
    在JS中生成不重复的随机数在JS中生成不重复的随机数可以使用多种技术来实现。最初,该方法是通过将新生成的数字添加到数组并与其进行比较来检查是否已创建新生成的数字。但是,由于过多的递归调用,这可能会导致“超出最大调用堆栈大小”错误。一个有效的解决方案是生成一次随机数字列表,然后按顺序处理它。这种方法消...
    编程 发布于2024-11-08
  • 了解 MySQL 中的十进制数据类型
    了解 MySQL 中的十进制数据类型
    MySQL 中的 Decimal 数据类型对于金融相关项目至关重要,其中数值的精度至关重要。最近,我在 Ruby on Rails 项目之一中使用此数据类型时遇到了问题。让我分享一下我的经验和学到的东西。 挑战:超出范围的值错误 在我的项目期间,我在迁移文件中定义了 Decimal ...
    编程 发布于2024-11-08
  • Filament 如何使用 Trait(创建、更新)后重定向到列表页面
    Filament 如何使用 Trait(创建、更新)后重定向到列表页面
    要在 Filament v3 中创建或更新资源后重定向到列表页面,您可以在资源类中使用自定义特征。 创建自定义特征 <?php namespace App\Traits; trait RedirectIndex { protected function getRedirectUrl(...
    编程 发布于2024-11-08
  • 在阅读本文之前,请勿使用 Prisma ORM!
    在阅读本文之前,请勿使用 Prisma ORM!
    想象一下混乱情况,您在 NeonDB 中创建一个具有 0.5GB 存储空间的免费数据库,然后想,“很好,我将使用免费套餐进行测试” 。然后,几个小时后,收到了致命的电子邮件:“您的存储空间已被消耗!”。哇,你什么意思?连椅子都没有热起来!答案是什么呢?我使用了辉煌的 Prisma ORM,为了改进,...
    编程 发布于2024-11-08
  • Net 包如何影响 Go 程序中的死锁检测?
    Net 包如何影响 Go 程序中的死锁检测?
    网络包导入和死锁检测的相互作用在 Go 程序中,如果程序运行时通道操作阻塞,则程序最终会收到“死锁”错误。但是,当导入 net 包时,行为会发生变化。有问题的代码片段:package main import ( "fmt" "net/http"...
    编程 发布于2024-11-08
  • 如何从 MySQL 列数据构造 PHP 数组?
    如何从 MySQL 列数据构造 PHP 数组?
    从 MySQL 列数据构造 PHP 数组使用 mysql_fetch_array 从 MySQL 列检索数据会产生一个表示单行的数组。要创建一个由特定列中所有行的值组成的数组,一种有效的方法是迭代该数组并组装一个新数组:$column = array(); while ($row = mysql_f...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3