关于 JavaScript 中的 Promises

2025-05-24

关于 JavaScript 中的 Promises

在 JavaScript 中,Promise 是一个对象,它表示一个可能尚未可用但将来会得到解决的值。Promise 用于处理异步操作,例如发出网络请求或访问数据库,这些操作的结果并非立即可用。

如果你准备好了,我想开始我们的冒险。


承诺如何发挥作用?

APromise是 Promise 创建时不一定已知的值的代理。它允许您将处理程序与异步操作的最终成功值或失败原因关联起来。这使得异步方法可以像同步方法一样返回值:异步方法不是立即返回最终值,而是返回一个 Promise,用于在未来某个时间点提供该值。

Promise 如何运作


Promise 有三种可能的状态:

Promise 有三种可能的状态

  1. 待处理: Promise 的初始状态。Promise 既未实现,也未拒绝。
  2. 已实现:该承诺已得到解决,并且结果值可用。
  3. 已拒绝: Promise 已被拒绝,并且发生错误。

一旦 Promise 被解决,就无法再重新设置。orresolve()函数reject()只能调用一次,之后对这些函数的任何调用都将无效。已解决 Promise 的不变性是一项重要特性,因为它确保了 Promise 的值保持一致且可预测。一旦 Promise 被解决,其值就无法更改,这有助于防止意外行为,并使代码推理更容易。


如何创建承诺?

Promise 是使用Promise构造函数创建的,该构造函数接受一个参数,即名为executor 的函数。executor 函数接受两个参数:resolvereject。这两个函数在 Promise 状态为fulfilledrejected时被调用。

向你展示我的意思......

创建延迟后解析的 Promise 的示例

上面例子中的 Promise 将在一秒后解析,解析后的 Promise 的值将是用户数组。

创建 Promise 后,您可以使用该then方法附加一个回调函数,该函数将在 Promise 完成时调用。该then方法接受两个参数:一个用于已解析值的回调函数,一个用于已拒绝值的回调函数。

向你展示我的意思......

Promise 示例

承诺示例的输出


继续我们的冒险,让我们看一个被拒绝的 Promise 的例子。

向你展示我的意思......

被拒绝的承诺

输出已被拒绝的承诺


链式承诺

以下方法用于将后续操作与已解决的 Promise 关联起来。由于这些方法返回 Promise,因此可以将它们串联起来

Promise.prototype.then()
Promise.prototype.catch()
Promise.prototype.finally()
Enter fullscreen mode Exit fullscreen mode

JavaScript 中的链式承诺

JavaScript 中的 Promise 链式执行指的是创建一系列依次执行的 Promise。链中的每个 Promise 都依赖于前一个 Promise 的成功执行,因此,如果链中任何一个 Promise 失败,整个链都会失败。

让我们看看如何在 JavaScript 中链接承诺:

JavaScript 中链式承诺的示例

输出:JavaScript 中链式承诺的示例

这里,该fetchData()函数用于从远程 API 获取数据并执行某些操作。该fetchData()函数返回一个 Promise,该 Promise 会解析操作的结果。

Promise 链首先从 API 获取用户数据,然后使用第一个用户的 ID 获取其帖子,最后使用第一篇帖子的 ID 获取该帖子的评论。then()链中的每个方法都会处理前一个 Promise 的解析值,最后一个catch()方法会处理链中发生的任何错误。

我们可以根据需要创建多个带有then()方法的链。与同步代码一样,链式调用将产生串行运行的序列。我们来看一个简单的例子。

许多链


Promise 的好处

与传统的基于回调的方法相比,Promises 在 JavaScript 中处理异步操作具有诸多优势。其中一些主要优势包括:

  1. 更佳的可读性:与传统的基于回调的方法相比,Promises 能让您编写更易读、更易于理解的代码。借助 Promises,您可以将异步操作按顺序串联起来,从而明确操作的执行顺序。

  2. 改进的错误处理: Promises 可以更轻松地处理异步操作期间发生的错误。借助 Promises,您可以使用 catch 方法处理链中任何步骤发生的错误,而不必为每个步骤单独处理错误。

  3. 避免回调地狱: Promises 可以帮助您避免“回调地狱”,即您拥有一连串嵌套回调,导致难以管理和调试的情况。使用 Promises,您可以将异步操作串联起来,而无需嵌套多层回调。

  4. 能够返回值: Promises 允许你从异步操作中返回一个值,这使得将一个操作的结果按顺序传递给另一个操作变得更加容易。当你需要按顺序执行多个异步操作,并且需要在下一个操作中使用每个操作的结果时,此功能尤其有用。

  5. 更好的兼容性: Promises 是现代 JavaScript 中的标准化功能,并且所有现代浏览器和 Node.js 都支持。这意味着 Promises 可以在不同的环境中使用,而无需为每个环境编写不同的代码。


我如何取消承诺?

在现代 JavaScript 中,Promise 一旦创建就无法取消。它会执行其代码,要么 resolve,要么 throw,并且没有内置的取消操作的方法。

您可以使用一些技术来模拟取消:

  1. 超时:如果 Promise 解析时间过长,你可以使用超时来拒绝它。如果你正在发出网络请求并希望限制其耗时,这项技术非常有用。

  2. 中止网络请求:您可以使用中止控制器中止网络请求。Fetch API 提供了一个 AbortController API,允许您在网络请求完成之前取消它。

  3. 使用标志:您可以在代码中使用标志来模拟取消操作。您可以将标志设置为 true,以指示应取消该操作,然后在 Promise 代码中检查该标志,以确定是继续执行该 Promise 还是拒绝该 Promise。

值得注意的是,这些技术都不能真正取消 Promise;它们只是提前将其拒绝。如果您需要真正取消,则可能需要使用提供取消支持的库,例如rxjsbluebird


蓝鸟承诺取消

Bluebird是一个流行的 JavaScript Promise 库,它提供了包括 Promise 取消在内的高级功能。Promise 取消是指取消 Promise 的功能,这对于取消正在进行或长时间运行的异步操作非常有用。

在 Bluebird 的帮助下,可以使用Promise.cancel()方法来取消 Promise。此方法不属于标准 Promise API,是 Bluebird 特有的。

要在 Bluebird 中使用 Promise 取消功能,你需要使用构造函数创建一个可取消的 Promise new Promise(),并将一个取消函数作为参数传入。取消 Promise 时,将调用该取消函数。

蓝吟诗人的例子


并行多个 Promise

借助Promises,可以更轻松地并行管理和执行多个异步操作,并等待所有操作完成后再继续。

向你展示我的意思......

使用以下语法创建了四个 Promise new Promise()。每个 Promise 都会使用方法在一定超时时间后被解决拒绝setTimeout()error函数被定义为将任何错误记录到控制台。

承诺

创建上述承诺后,现在我们将看到使用不同 Promise 方法的实例。

Promise.all() 方法

下面的实例使用了Promise.all()一个方法,该方法接受一个 Promise 数组作为参数,并等待所有 Promise 都已完成。一旦所有 Promise 都已完成,then()该方法就会执行,并按照 Promise 数组中传入的顺序返回一个值数组。在本例中,所有三个 Promise 都已完成,并且它们的值会被打印到控制台。

这是一种很好的方法,例如使用两个不同的请求获取数据,然后在两个请求完成后将它们合并。

Promise.all() 方法

Promise.any() 方法

下面的实例使用了Promise.any()一个方法,该方法接受一个 Promise 数组作为参数,并等待其中任何一个 Promise 被 fulfilled。一旦第一个 Promise 被 resolve,then()方法就会被执行,并返回第一个 Promise 的 resolved 值。在本例中,第三个 Promise 比其他两个 Promise 先 resolve,其值会被打印到控制台。

下面实例使用

Promise.race() 方法

下面的实例使用了Promise.race()一个方法,该方法接受一个 Promise 数组作为参数,并等待第一个 Promise 被 resolve 或 rejected。一旦第一个 Promise 被解决,then()就会执行一个方法,返回第一个已解决 Promise 的 resolve 或 rejection 值。在本例中,第三个 Promise 比其他两个 Promise 先被 resolve,因此它的值会被打印到控制台。

Promise.race() 方法

Promise.allSettled() 方法

下面的实例使用了Promise.allSettled()一个方法,该方法接受一个 Promise 数组作为参数,并等待所有 Promise 都已解决(即,已解决或已拒绝)。一旦所有 Promise 都已解决,then()该方法就会执行,并返回一个对象数组,每个对象包含每个 Promise 的状态(或原因)。在本例中,所有 Promise 都已解决,因此所有 Promise 的状态和值(或原因)都会被打印到控制台上。

Promise.allSettled() 方法


结论

Fetch API 是旧版 XMLHttpRequest 对象的现代替代品,它基于 Promise。当您使用 Fetch API 发出请求时,会返回一个解析为响应对象的 Promise。这允许您使用该then()方法以简洁易读的方式处理响应。

异步函数是 JavaScript 的一个新特性,它基于 Promises 构建。异步函数允许你编写看起来像同步代码的异步代码,使其更易于阅读和编写。异步函数使用 await 关键字等待 Promises 解析后再继续执行,这使得编写看起来像一系列同步语句的异步代码成为可能。

在这两种用法中,Promises 都用于以简洁易读的方式处理异步操作。通过使用 Promises,你可以避免回调地狱,并编写易于理解的异步代码。


动机

提醒:
无论别人怎么说、怎么想,你都很棒。

无论别人怎么说、怎么想,你都很棒


🍀支持

请考虑关注并支持我们,订阅我们的频道。非常感谢您的支持,这将帮助我们继续创作您喜爱的内容。提前感谢您的支持!

YouTube
Discord
GitHub


谢谢

文章来源:https://dev.to/codeofrelevancy/all-about-promises-in-javascript-39lj
PREV
在 CSS 中将 div 居中的 3 种方法
NEXT
面向使用 Visual Studio Code 的用户的 Vim(全文)想要更多提示吗?