JavaScript 中的 Promise,变化与优化

前言

在 JavaScript 中,Promise 已经是必不可少的元素了。因为在异步操作上,Promise 比传统的回调函数要更直观、可维护性更高,而且可以解决回调地狱(callback hell)的问题。

在ES6之前,Promise对象的设计遵循了Promises/A+规范,但在ES6中,Promises/A+规范完全被全局Promise替代。

在最新版本的ECMAScript中,Promise出现了新的API——Promise.allSettled(即Promise.allSettled()方法)。那么,接下来我们就来详细学习一下Promise.allSettled吧!

Promise 基础

在ES6之前,处理异步操作的方式通常是通过回调函数来实现:

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

但是这种处理异步操作的方式有一个明显的缺点,就是代码嵌套太深,导致可读性非常差。

而 Promise 可以简单而优雅的解决这个问题。我们可以简单地使用 Promise 来封装异步操作:

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

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

上述代码相比于回调函数要清晰简单很多。如果出错,也可以通过 catch 捕捉到错误。

Promise.all

Promise.all 方法比较常用,在处理多个 Promise 实例时可以把多个 Promise 实例的值混合处理。Promise.all 接受一个 Promise 实例的数组作为参数,当接收到多个 Promise 实例返回值之后,会将所有实例的返回结果以数组形式返回。

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

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

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

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

在上述代码中,getUser1、getUser2、getUser3 都是异步函数,分别在 500 毫秒后分别正常返回了数字 1、2 和返回错误 3.

而在 Promise.all 的 then 函数中,我们得到了一个包含 1、2 的数组,同时用户的错误也被 catch 到了。

Promise.allSettled

与 Promise.all 不同,Promise.allSettled 方法会等待所有 Promise 实例都返回对应的状态(不论是 resolved 还是 rejected),只有所有实例的状态都被转化为 settled 后,Promise.allSettled 才会执行。

例如,在下面这个例子中,getUser1、getUser2、getUser3 都返回了正确的值,但是在 getUser4 中出错了,Promise.allSettled 依然会异步等待所有的返回,最终返回状态集合。

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

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

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

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

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

在这个例子中,我们使用了 getUser4 函数,并在其中引发了错误。但是,Promise.allSettled 还是会异步等待结果并返回一个结果状态的集合。

结果中每个对象都有一个 status 属性,该属性是 settled、fulfilled、rejected 中的一个。

我们来看看返回值:

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

可以看到,每个 Promise 实例的状态都被等待到之后才执行,而且其中的 fulfilled 或者 reject 状态也以对象形式被统一返回了。

为了更形象一些,我们来看看下面的代码:

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

这个代码在前两个 Promise 实例中是已知的。可以看到,我们使用 Promise.resolve 和 Promise 构造函数来创建返回数字 3 和字符串 'foo' 的 Promise 实例,而结果数组始终都是相同的:

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

Promise.allSettled 的使用

Promise.allSettled 在某些情况下比 Promise.all 更加有用。当 Promise 数组中有 Promise 实例的状态不确定时, Promise.all 会挂起并等待所有 Promise 实例都返回, 而 Promise.allSettled 不会等待所有 Promise 实例都返回,它只是等待所有 Promise 实例都准备好返回。

在下面的代码中,getUser1 和 getUser2 都返回了相应的成功信息,但是 getUser3 函数在进行异步操作的时候会引发 Error。在这种情况下,Promise.all 会被拒绝并返回一个错误的菜单,而Promise.allSettled依然会执行并返回所有值集合的状态。

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

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

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

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

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

这是包含 catch 函数的 Promise.all 和包含 then 函数的 Promise.allSettled 的输出结果:

结果 1:

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

结果 2:

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

在这个例子中,我们使用了 getUser3 函数并引发了错误。但是,在使用 Promise.all 时,我们只会得到一个错误,而使用 Promise.allSettled 时我们会得到三种不同的状态值集合。

总结

在本文中,我们详细学习了 JavaScript 中的 Promise 及其基本使用和优化的知识。同时,我们重点介绍了 Promise.allSettled 方法,因为对于处理异步操作时,这个方法比 Promise.all 更加实用和有意义。

要使得代码更加简洁和可读,同时所处理的异步操作序列更加优美和直观,我们可以结合 Promises 与 Promise.allSettled,在 Promise 链中嵌入 Promise.allSettled 来获得异步过程中的更多信息。

无论是 Promise.all 为多个 Promise 实例返回值的混合处理,还是 Promise.allSettled 提供了一个比 Promise.all 更细致更完整状态集合,他们恰好在不同情形下都有优越之处。

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


猜你喜欢

  • RxJS 实现鼠标跟随效果

    RxJS 是一个支持响应式编程的 JavaScript 库,其提供的 API 可以帮助我们更方便地处理异步数据流。本文将介绍 RxJS 如何实现鼠标跟随效果,并探讨其在前端开发中的应用。

    1 年前
  • TypeScript 中的泛型详解

    在 TypeScript 中,泛型是一种可以让我们在编写代码的时候更加灵活的工具。通过使用泛型,我们可以编写更加通用的代码,而不需要为每种类型都编写一份代码。在接下来的内容中,我们将详细讨论 Type...

    1 年前
  • 在 React Native 中使用 GraphQL 的方式

    在 React Native 中使用 GraphQL 的方式 GraphQL 是一种现代的、高效的数据查询和操作语言,它为前端和后端之间的数据交互提供了一种全新的方式。

    1 年前
  • Angularjs 中的指令解析

    什么是 Angularjs 指令? Angularjs 中的指令是一些特殊的属性或标签,它们提供了非常丰富的功能和灵活性,可以用来扩展 HTML 标签的功能,完成复杂的业务逻辑,实现数据绑定以及事件监...

    1 年前
  • Vue.js 实现树形控件的方法

    树形控件是前端开发中常见的组件之一,它能够清晰地展示数据之间的层次关系。Vue.js 是一个流行的前端框架,它提供了一种方便的方法来实现树形控件。本文将介绍实现树形控件的方法,帮助读者更好地理解 Vu...

    1 年前
  • ES9 中的 Class Fields 提升了 ES6 的 “Class” 的语法糖

    随着前端发展的不断壮大,JavaScript 已经成为了最为常见的编程语言之一。而在 ES9 中,新增的 Class Fields 功能为开发人员提供了更便捷的 class 编写方式。

    1 年前
  • 从零构建 Serverless 应用程序:入门指南

    Serverless 技术近年来风靡全球,在前端领域中也备受推崇。使用 Serverless 技术可以省去很多传统应用程序中必须要考虑的事情,比如服务器承载、部署和维护等等。

    1 年前
  • Sequelize 如何使用 Op.or?

    介绍 Sequelize 是 Node.js 下的一款 ORM (Object-Relational Mapping) 库,可以让开发者在 Node.js 应用中操作数据库更加方便和高效。

    1 年前
  • 解析 Promise 的 then 和 resolve 方法

    在前端开发中,我们经常使用 Promise 进行异步处理。 Promise 是一个对象,它表示一个异步操作的最终完成(或失败)及其结果值的表示。 Promise 对象最主要的两个方法分别是 then ...

    1 年前
  • SASS 中使用 @extend 继承样式

    在前端开发中,使用 CSS 进行页面样式设计是非常重要的一部分。随着项目规模不断扩大,代码复杂度也会随之增加。为了提高代码的可读性和维护性,我们需要使用一些工具来简化样式的编写和管理。

    1 年前
  • 利用 Enzyme 测试 React 组件中的异步操作

    引言 在前端开发中,React 组件已经成为了构建用户界面的主流技术。而在 React 组件的开发过程中,异步操作无疑是必不可少的。但是,如何测试异步操作又成为了难点之一。

    1 年前
  • 从 jQuery 到 React:一个前端工程师的转型经历

    作为一个有多年前端开发经验的工程师,我见证了前端技术的不断变革和迭代。从最开始使用 jQuery 来处理 DOM,到后来的 MV* 框架,再到目前前端技术的主流 React,我不断认知提升和技术转型的...

    1 年前
  • Web 性能优化 — 三分之一时间卡在白屏上

    Web 应用的性能一直是开发者和用户非常关注的问题。在当前的互联网时代,用户对网站的访问速度及加载速度有着非常高的要求。有数据表明,网站加载时间过长会直接影响用户体验,导致用户流失率增加。

    1 年前
  • PWA 应用如何支持多种浏览器缓存 API

    前言 近年来,随着 Web 技术的不断发展,越来越多的 Web 应用开始演化成 Progressive Web App(PWA)。随着 PWA 技术的流行,Web 开发者们需要不断地学习更新技术,以便...

    1 年前
  • LESS 中的单位 px、em、rem 的使用方法

    在开发前端页面时,我们经常会遇到需要设置元素尺寸以及距离等场景。而在设置这些数值时,我们可能会使用像素(px)、em 和 rem 等单位。那么在 LESS 中,这些单位该如何使用呢? px 像素是我们...

    1 年前
  • 使用 CSS Grid 实现各种著名布局

    CSS Grid 是一个强大的布局系统,可以快速、简单地创建各种布局效果。在这篇文章中,我们将使用 CSS Grid 实现各种著名布局的例子,并探讨如何使用 CSS Grid 更有效地创建网页布局。

    1 年前
  • Next.js 项目如何支持 CSS Modules

    CSS Modules 是一种将 CSS 作用域限制到当前组件范围内的技术,它可以避免全局 CSS 样式冲突的问题。在使用 Next.js 开发项目时,我们也可以轻松地使用 CSS Modules。

    1 年前
  • Mongoose 中的默认排序方式详解

    Mongoose 是一个 Node.js 的 MongoDB 驱动程序,它提供了对 MongoDB 数据库操作的封装。在实际项目中,常常需要对数据库的查询结果进行排序。

    1 年前
  • 使用 Custom Elements 实现 Dropdown 组件详解

    随着前端技术的飞速发展,组件化开发成为了前端开发者必备的技能之一。而 Custom Elements 正是实现组件化开发的有力武器之一,它可以帮助我们快速构建通用的组件并在各种场景中复用。

    1 年前
  • # MongoDB 索引优化的技巧与方法

    MongoDB 索引优化的技巧与方法 前言 MongoDB 是一个非常强大的文档型数据库,其提供了丰富的索引机制使得我们能够更高效地进行数据查询和操作。然而,当数据量增长时,索引也需要不断优化以保证系...

    1 年前

相关推荐

    暂无文章