Promise 中 then 和 catch 执行顺序问题详解

Promise 是前端开发中常用的异步编程方法之一,但是在使用 Promise 的时候,经常会遇到其中 then 和 catch 的执行顺序问题,特别是当 Promise 链式调用的时候,更需要注意这个问题。本文将详细讲解 Promise 中 then 和 catch 的执行顺序问题,并给出一些示例代码帮助读者更好地理解以及掌握这个问题。

Promise 是什么?

Promise 是一种表示异步操作的对象,可以看作是异步编程的一种解决方案。它提供了状态转换机制,可以表示异步操作成功、失败、或者正在进行中等状态。Promise 对象最终将变成两种状态之一:resolved(成功)或 rejected(失败)。并且,通过 then 和 catch 方法可以注册回调函数,用于在 Promise 对象的状态发生变化后执行自定义的操作。

then 和 catch

Promise 中的 then 和 catch 方法用于注册当 Promise 对象状态变化之后需要执行的回调函数。then 方法用于注册当 Promise 对象已成功时需要执行的回调函数,而 catch 方法用于注册当 Promise 对象被拒绝时需要执行的回调函数。

----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    -------------- --------
  -- ------
---

-------
  -------------- -- -
    ---------------------- -- --------
  --
  -------------- -- -
    ---------------------- -- -------
  ---

在上面的示例中,我们创建了一个 Promise 对象,设置了一个 1 秒的定时器,然后在定时器回调函数中使用 resolve 方法将 Promise 对象转换成 resolved 状态,并传递了一个参数 "Hello World"。接着,我们使用 then 方法注册了一个回调函数,用于处理 Promise 对象状态已成功的情况,这个回调函数会输出 "Resolved: Hello World"。如果 Promise 对象变成 rejected 状态,则会执行 catch 方法注册的回调函数。

需要注意的是,通过 then 方法注册的回调函数必须返回一个值,这个值可以是一个新的 Promise 对象,也可以是一个非 Promise 对象的值。如果返回的是一个新的 Promise 对象,那么需要等待这个新的 Promise 对象状态改变之后,才会执行下一个 then 或者 catch 方法的回调函数。如果返回的是一个非 Promise 对象的值,则会将这个值包装成一个 Promise 对象,并立即执行下一个 then 或者 catch 方法的回调函数。

then 方法执行顺序

在使用 then 方法时,可以链式调用多个 then 方法,每个 then 方法注册的回调函数可以根据之前 then 方法返回的值来确定最终返回的值。而在这个过程中,then 方法的执行顺序是非常关键的。一般来说,then 方法注册的回调函数会按照注册的顺序依次执行,也就是说,后注册的回调函数会等待前面的回调函数执行完毕才会开始执行。

----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    -----------
  -- ------
---

-------
  -------------- -- -
    ------------------ ----- -- --------
    ------ ------ - --
  --
  -------------- -- -
    ------------------- ----- -- --------
    ------ ------ - --
  --
  -------------- -- -
    ------------------ ----- -- --------
    ------ ------ - --
  ---

在上面的示例中,我们创建了一个 Promise 对象,设置了一个 1 秒的定时器,然后在定时器回调函数中使用 resolve 方法将 Promise 对象转换成 resolved 状态,并传递了一个参数 1。接着,我们使用 then 方法连续注册了三个回调函数,每个回调函数都会将上一个回调函数的返回值加上 1 并作为自己的返回值。在输出结果中可以看到,第一个 then 方法的回调函数会在 1 秒后执行并输出 "first then: 1",第二个 then 方法的回调函数会在第一个回调函数执行完毕之后执行,并输出 "second then: 2",第三个 then 方法的回调函数也会等待前面的回调函数执行完毕之后执行,并输出 "third then: 3"。

catch 方法执行顺序

和 then 方法类似,catch 方法也支持链式调用,每个 catch 方法注册的回调函数会按照注册的顺序依次执行,也就是说,后注册的回调函数会等待前面的回调函数执行完毕才会开始执行。

----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    ---------- ---------------- ---- ---------
  -- ------
---

-------
  -------------- -- -
    ---------------------- -- --------
  --
  -------------- -- -
    ------------------ ------ -- ---------------
  --
  -------------- -- -
    ------------------- ------ -- ---------------
  ---

在上面的示例中,我们创建了一个 Promise 对象,设置了一个 1 秒的定时器,然后在定时器回调函数中使用 reject 方法将 Promise 对象转换成 rejected 状态,并传递了一个 Error 对象。接着,我们使用 catch 方法连续注册了两个回调函数,每个回调函数都会输出上一个回调函数的错误信息。在输出结果中可以看到,第一个 catch 方法的回调函数会在 1 秒后执行并输出 "first catch: Something went wrong",第二个 catch 方法的回调函数会等待第一个回调函数执行完毕之后执行,并输出 "second catch: Something went wrong"。

then 和 catch 执行顺序问题

当 Promise 对象状态变成 resolved 时,注册的 then 方法会依次执行,直到所有的 then 方法执行完毕。当 Promise 对象状态变成 rejected 时,注册的 catch 方法会依次执行,直到所有的 catch 方法执行完毕。但是,如果在 Promise 链式调用中,某个 then 方法传递给下一个 then 方法的是一个 rejected 状态的 Promise 对象,那么直接跳到下一个 catch 方法,不再执行后续的 then 方法。因此,then 和 catch 的执行顺序问题,就是指当 Promise 对象状态发生变化时,then 和 catch 方法的执行顺序有哪些特点和需要注意的地方。

----- ------- - --- ----------------- ------- -- -
  ------------- -- -
    ---------- ---------------- ---- ---------
  -- ------
---

-------
  -------------- -- -
    ---------------------- -- --------
  --
  -------------- -- -
    ------------------- ----- -- --------
  --
  -------------- -- -
    ------------------- -- ---------------
  ---

在上面的示例中,我们创建了一个 Promise 对象,设置了一个 1 秒的定时器,然后在定时器回调函数中使用 reject 方法将 Promise 对象转换成 rejected 状态,并传递了一个 Error 对象。接着,我们使用 then 方法注册了一个回调函数,然后又使用一个 then 方法注册了另一个回调函数。此时,由于 Promise 对象的状态已经变成 rejected,因此会直接跳到 catch 方法,并执行 catch 方法的回调函数。在输出结果中可以看到,程序会输出 "Catch: Something went wrong",而不会执行后面那个 then 方法的回调函数。

总结

Promise 是前端开发中常用的异步编程方法之一,在使用 Promise 的过程中,then 和 catch 方法是非常重要的一部分。理解并掌握 then 和 catch 方法的执行顺序问题,是编写高质量代码的关键之一。在编写代码时,需要根据具体业务场景合理地选择使用 then 和 catch 方法,才能使代码更加健壮、高效。下面是一些需要注意的地方:

  1. then 方法的回调函数需要返回一个值,可以是一个新的 Promise 对象,也可以是一个非 Promise 对象的值。

  2. 在 Promise 链式调用中,如果某个 then 方法传递给下一个 then 方法的是一个 rejected 状态的 Promise 对象,直接跳到下一个 catch 方法,不再执行后续的 then 方法。

  3. then 方法注册的回调函数会按照注册的顺序依次执行,后注册的回调函数会等待前面的回调函数执行完毕才会开始执行。

  4. catch 方法也支持链式调用,每个 catch 方法注册的回调函数会按照注册的顺序依次执行,后注册的回调函数会等待前面的回调函数执行完毕才会开始执行。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/64cbbdb75ad90b6d04222861


猜你喜欢

  • ESLint 如何检查函数是否有返回值

    ESLint 是一个开源的 JavaScript 代码检查工具,它能够帮助前端开发者在代码编写过程中发现常见的代码错误,并且还支持多种自定义规则的开发,以适应团队的具体需求。

    1 年前
  • 如何在 Sequelize 中使用事务来控制数据库交易

    在进行数据库交易时,我们经常需要考虑事务的使用。事务可以确保在某些操作失败时回滚所有对数据库的更改,从而避免数据不一致的问题。在 Sequelize 中,我们可以使用事务来控制数据库交易。

    1 年前
  • RxJS 中 zip 的原理及实现方式

    前言 在 RxJS 中,zip 是一个非常有用的操作符,它可以将多个 Observable 按照顺序一一对应,从而得到一个新的 Observable。这个新的 Observable 会在每个源 Obs...

    1 年前
  • Web 与 PWA 架构设计方案比较

    引言 Web 应用一直是互联网世界的重要组成部分,但是原生应用和 PWA 已经在移动端开始逐渐风靡。那么,PWA 和传统的 Web 应用相比,架构设计方案有哪些不同呢?对于前端开发者来说,应该如何根据...

    1 年前
  • ECMAScript 2021(ES12)中Generator的使用详解

    Generator是JavaScript中一个比较特殊的函数,它可以被暂停和恢复,并且可以在不阻塞当前线程的情况下,将反复和异步代码转换为同步代码执行。 在ES6之前,JavaScript中没有这样的...

    1 年前
  • Promise 在 CSS3 动画中的应用实例分享

    在前端动画开发中,我们经常需要运用 CSS3 实现动画效果。但在实际操作过程中,经常会遇到异步的情况,例如当我们需要按顺序加载多个 CSS3 动画时,每个动画结束后,才能顺序执行下一个动画。

    1 年前
  • ES10 采用的新正则特性解析及使用教程

    ES10 采用的新正则特性解析及使用教程 正则表达式是前端开发中常用的一种技术。ES10 中新增了一些新的正则特性,本篇文章就来详细解析这些新特性,并提供相应的使用教程与示例代码。

    1 年前
  • 在 Fastify 框架中使用 Websockets 搭建聊天室

    前言 在前端开发中,使用 Websockets 技术实现实时通讯功能已经成为了一种常见的需求,而 Fastify 是一个高效且易用的 Node.js Web 开发框架,它的设计目标是提供一种基于 Ty...

    1 年前
  • Web Components 实现一个带图片的轮播组件

    Web Components 是一种通过组合原生 HTML、CSS 和 JavaScript 的方式开发可重用的用户界面组件的技术。它使得前端开发人员可以通过封装可重复使用的功能和界面,使得整个项目的...

    1 年前
  • Kubernetes 健康检查回顾

    背景 Kubernetes 是一款流行的容器编排平台,它为我们提供了一个高度自动化的环境来部署、扩展和管理容器化应用程序。然而,保证 Kubernetes 集群中的容器应用程序的健康状态并不总是一件容...

    1 年前
  • 初学 Docker 篇:用 Docker Compose 搭建 Web 服务

    在现代 Web 开发过程中,容器化技术已经成为了一个必不可缺的组成部分。Docker 是一种流行的容器化技术,它可以自动化地打包和部署应用程序及其依赖项。 本文将介绍如何使用 Docker Compo...

    1 年前
  • 构建具有多语言支持的 Angular 应用程序的步骤和技巧

    随着全球化的趋势不断发展,越来越多的企业和组织需要为其应用程序添加多语言支持。在 Angular 中实现多语言支持相对容易,但是需要遵循一些步骤和技巧。在本文中,我们将讨论如何构建具有多语言支持的 A...

    1 年前
  • Next.js 应用如何配置 CDN 加速

    前言 现在的 Web 应用越来越重,引入的依赖多、页面组件多,加载速度逐渐成为用户体验的重要指标。为了提升网站性能,我们可以采用 CDN(内容分发网络)来缓存静态资源并加速访问速度。

    1 年前
  • Mocha 测试框架中如何使用 TypeScript 编写测试代码

    前言 在 Web 前端开发中,测试是至关重要的环节,能够有效保证软件质量,保障软件功能可靠性。而 Mocha是一款使用Javascript编写测试的框架。但是,随着前端项目变得越来越复杂,使用 Jav...

    1 年前
  • Deno 中如何处理 HTTP 请求的错误?

    在 Deno 中,我们可以通过内置的 fetch 函数来进行 HTTP 请求。但是,由于网络传输的不确定性,我们也需要处理 HTTP 请求中可能遇到的错误。 下面,我们将一步步地介绍在 Deno 中如...

    1 年前
  • 如何在 Webpack 中使用 GraphQL?

    如果你是一个前端开发者,你肯定听说过 Webpack 这个强大的构建工具。Webapck 已经成为了前端应用程序开发的标配。GraphQL 也是一个由 Facebook 开发的强大的查询语言, 可以让...

    1 年前
  • Babel 框架升级后出现的 BUG 及解决方案

    1. 背景 随着前端技术的不断发展,新的框架和工具层出不穷。Babel 作为前端开发中广泛使用的语法编译工具,在最近的升级过程中出现了一些 BUG,这给广大开发者带来了一定的困扰。

    1 年前
  • 学习 ES7 的 Array.prototype.fill 方法,让数组填充操作更加简单高效

    介绍 在前端开发中,数组是常用的数据结构之一。数组提供了各种便利的操作方法,其中 fill 方法是 ES7 新增的一个方法。这个方法可以快速、简单地填充数组,提高了数组填充操作的效率和方便性。

    1 年前
  • MongoDB 数据备份和还原方法详解

    MongoDB 是一款非关系型数据库 (NoSQL),由于其高性能、可扩展性和可靠性等特点,已成为 Web 开发领域中备受欢迎的数据库之一。在使用 MongoDB 数据库时,如何进行数据备份和数据还原...

    1 年前
  • ES8 中的 Object.getOwnPropertyDescriptors() 方法控制对象属性行为

    在 JavaScript 中,对象是一等公民。我们可以通过对象来封装数据,定义方法,甚至是创建类和实例。在实际的开发场景中,我们常常需要操作对象的属性,例如获取、添加、修改或者删除属性等。

    1 年前

相关推荐

    暂无文章