当前位置: 首页 > news >正文

ES6中的Promise对象

1. Promise是什么

Promise简单来说就是一个容器,里面保存着未来才会结束的事件的结果(这个事件就是异步操作)。Promise是一个对象(构造函数),可以获取异步操作的结果。

特点:

  • 对象的状态不受外界影响。有三种状态分别是Pending(进行中)、Fulfilled(已成功)、Rejected(已失败),这三种状态只能是异步的结果决定,其他操作都不能改变。

  • 状态改变后不会再变,任何时候都可以得到这个结果。状态改变只有两种情况分别是进行中变成成功、进行中变成失败。就是算已经发生变化,再对Promise添加回调函数
    也会立即得到这个结果,而事件(event)则是错过了监听就得不到结果了。

2. 为什么会出现Promise

因为之前解决异步操作使用回调函数,会嵌套多层,影响编写阅读,而Promise的出现更容易实现,使异步操作可以看出同步操作,阅读更容易。

3. Promise基本用法

const promise = new Promise((resolve, reject) => {if (/* 异步操作成功*/) {resolve(value)} else {reject(value)}
})

Promise构造函数接受一个函数作为参数,这个函数有两个参数分别是resolvereject,这两个参数也是函数。

resolve的作用就是将Promise对象的状态从进行中变为成功,在异步操作成功时进行调用,并将异步操作的结果作为参数传递出去。

reject的作用就是将Promise对象的状态从进行中变为失败,在异步操作失败时进行调用,并将异步操作的错误结果作为参数传递出去。

1. then回调函数

当Promise实例生成后可以使用then方法分别指定resolvedrejected状态的回调函数

then方法接受两个回调函数作为参数,第一个参数是Promise对象状态变为resolved时调用,第二个参数是Promise对象状态变为rejected时调用,其中第二个参数是可选的,
这两个函数的参数都是Promise对象传过的值当作为参数

promise.then((value) => {// 成功执行的代码
}, (error) => {// 失败执行的代码
})

2. then方法执行顺序

Promise对象建立后会立即执行,但是then方法指定的回调函数会在当前脚本所有同步任务执行完成后才会执行。通俗讲比如说现在处在一个方法中,then后还有代码,
比如正常的代码或者异步代码,它执行时会自动在正常代码(同步)后面执行。

const promise = () => {new Promise((resolve, reject) => {console.log('Promise实例')resolve('hello')}).then(result => {console.log('.then方法')})console.log('Promise外的打印');const list = [1, 2, 3];list.map((item, index) => {console.log(item, 'map打印' + index);})
}
promise();

promise_order.png

3. resolve、reject函数的参数

reject函数的参数通常是Error对象的实例,表示抛出的错误。

resolve函数的参数除了正常值外,可以是Promise实例,如果是Promise实例则需要特别的注意。

如果传入的是一个实例p2,则本实例p1的状态取决于传入p2的状态,假如p1将要变成成功的状态,而传入的p2则为失败状态,则p1会执行失败状态时的代码。p1会等待p2实例的状态转变。

const p2 = new Promise((resolve, reject) => {reject(new Error('fail'));
})const p1 = new Promise((resolve, reject) => {resolve(p2);
})p1.then((result) => {console.log(result);
}).catch((error) => {console.log(error);
})
// 打印结果为:Error: fail

p2实例返回一个失败,本来p1是返回成功的,执行then方法,然后传入的参数是p2,而p2是一个实例,则此时的状态由p2决定,因此执行的是catch方法。

4. resolve 代码执行顺序

resolve函数所处脚本位置代码执行顺序和then方法一样,都是在本轮事件循环的末尾执行,总是晚于本脚本的同步任务。

const resolve = () => {new Promise((resolve, reject) => {resolve('状态成功后传递的值');console.log('脚本其他同步代码');}).then((result) => {console.log(result);})
}
resolve();

promise_resolve.png

从上面的代码可以看出,resolve函数后面的代码先执行了。

其实按正常来说resolve返回了成功时传递的信息,Promise也就完成了自己的使命,后面就不应该再有代码出现了,因此当书写代码时应该写在最后,或者可以使用
return语句,这样不会产生意外。

new Promise((resolve, reject) => {return resolve(1);// 这样后面的语句不会执行console.log(2);
})

4. Promise.prototype.then()

then方法是定义在了Promise实例原型对象上,作用就是为Promise实例状态改变时添加回调函数。

then方法的第一个参数是成功状态的回调函数,第二个参数可选是失败状态的回调函数。

then方法会返回一个新的Promise实例(不是之前的Promise实例),因此可以采用链式写法,可以接多个then方法,如果有多个then的方法,前面then方法
返回的结果会当成参数传入下一个回调函数。

5. Promise.prototype.catch()

catch方法其实就是then的第二个参数,用来指定发生错误时的回调函数。

  • 在捕获错误时,若then方法抛出错误也会捕获到。
  • 具有冒泡性质,抛出错误后会一直传递直到被捕获为止。
  • 如果没有catch方法,如果出错,不会传递到外层,没有任何反应
const someAsyncThing = () => {return new Promise((resolve, reject) => {// 下面一行报错,因为x没有声明resolve(x + 1);})
}
someAsyncThing();

promise_catch

上面加上一个catch方法或者then的第二个参数就能抛出错误。

  • catch方法一定要放在最后。

catch方法返回一个Promise对象,后面也是可以继续调用then,假如then方法抛出错误,若后面没有catch方法则不能被捕获到。

  • 如果状态已经变为失败,再抛错误无效
const catchError = () => {new Promise((resolve, reject) => {resolve('ok');throw new Error('发生错误');}).then((result) => {console.log(result);}).catch((err) => {console.log(err);})
}
catchError();

promise_catch_yijing

6. Promise.all()

Promise.all方法就是将多个Promise实例包装成一个新的Promise实例。

const p = Promise.all([p1, p2, p3]);

要求:

参数是一个数组形式,且每一项必须为Promise实例,假如不是实例则会调用Promise.resolve转化成Promise实例。

1. 新实例的状态

p的状态由参数的状态决定,分为两种情况。

第一种:所有的参数状态都变成Fulfilled(成功),则新实例变成Fulfilled,所有参数的返回值会组成一个数组,传递给新实例的回调函数。

第二种:如果有一个参数的状态变为Rejected(失败),则实例会变成Rejected,则会把这个结果传递给新实例的回调函数。

2. 参数实例是否有catch方法

如果作为参数的Promise实例自定义了catch方法,那么它被rejected时并不会触发Promise.all()的catch方法

这是为什么???

因为假如参数实例有catch方法时,执行完catch方法会返回一个新的Promise实例,此时的参数实例就会变为新返回的实例,
会变成resolved状态,会将catch方法执行完返回的值传递给all方法的回调函数。

// 参数p2有catch方法,最终结果为 ["hello", Error: 报错了]
const p1 = new Promise((resolve, reject) => {resolve('hello')}).then(result => result).catch(e => e);const p2 = new Promise((resolve, reject) => {throw new Error('报错了');}).then(result => result).catch(e => e);Promise.all([p1, p2]).then(result => console.log(result))  // ["hello", Error: 报错了].catch(e => console.log(e));

// 参数p2没有catch方法,会执行all的catch方法,输出Error: 报错了
const p1 = new Promise((resolve, reject) => {resolve('hello')
}).then(result => result).catch(e => e);const p2 = new Promise((resolve, reject) => {throw new Error('报错了');
}).then(result => result)Promise.all([p1, p2]).then(result => console.log(result)).catch(e => console.log(e)); // Error: 报错了

由此可见,假如项目中如果要求参数全部为成功的状态则每个参数尽量不要写catch方法,直接将catch方法写在all中。例如:上传多张图片,只有多个图片
上传成功后再请求接口,这样catch方法不能单个写。

7. Promise.race()

和Promise.all()类似,也是将多个Promise实例包装成一个新Promise实例,参数为数组。只不过是参数中只要有变化新实例的状态就会发生改变。

Promise.all是关系,Promise.race是关系

8. Promise.resolve()

功能是将一个对象转为Promise对象。

  • 参数是一个Promise实例

如果是Promise实例,会直接原封不动的返回。

  • 参数是thenable对象

???
thenable对象指的是具有then方法的对象。Promise.resolve方法会将对象转为Promise对象,然后立即执行其中的then方法。

const able = {then(resolve, reject) {resolve(1);}
}const p1 = Promise.resolve(able);
p1.then((value) => {console.log(value); // 1
})
  • 参数不具有then方法的对象或者更不不是对象

返回的实例就是Resolved状态,会直接执行回调函数。

  • 不带任何参数

就是返回一个Promise对象,但需要记住的是会在本轮事件循环结束时执行

8. Promise.reject()

生成一个状态未Rejected的Promise实例。

9. done()

因为不管then还是catch都是返回一个新的实例,可以采用链式写法,所以最后都以then,catch结尾,针对最后一个方法如果可能抛出错误,就可能无法捕获到,
可以使用done方法。永远处于尾端。

Promise.prototype.done = function (){this.then().catch((error) => {// 抛出一个全局错误throw new Error(error);})
}

10. finally()

也是用于末尾,与done最大的区别在于实例对象的最后状态不管是什么都会执行,接受一个回调函数作为参数。

Promise.prototype.finally = function (callback) {const p = this.constructor;return this.then((result) => p.resolve(callback().then(() => value)),(reason) => p.resolve(callback().then(() => reason)),)
}

相关文章:

ES6中的Promise对象

1. Promise是什么 Promise简单来说就是一个容器,里面保存着未来才会结束的事件的结果(这个事件就是异步操作)。Promise是一个对象(构造函数),可以获取异步操作的结果。 特点: 对象的状态不受外…...

vue 知识点———— 生命周期

1.什么是生命周期 Vue实例从创建到销毁的过程,叫生命周期。 从开始创建、初始化数据、编译模版、挂载Dom-渲染、更新-渲染、销毁等过程。 2.生命周期一共有几个阶段 创建前/后, 载入前/后,更新前/后,销毁前/销毁后 3.初始化相关属性 beforeCreate(创建前…...

焊接符号学习

欧美焊接符号举例 4.5------表示焊点直径 【3】------根据图示说明,表示此项为CC项或者SC项 6-------表示此处为第六CC项或者SC项 BETWEEN①AND②------表示①件和②件俩点之间的焊点 12X------表示俩点之间的焊点个数为12个 日本焊接符号举例 A------根据图示&…...

记录linux清理空间的步骤

sudo du -sh /* 看整体空间占用情况 [roothost ~]# sudo du -sh /* 0 /bin 143M /boot 85M /data 0 /dev 38M /etc 4.0K /home 0 /lib 0 /lib64 16K /lostfound 4.0K /media 4.0K /mnt 31M /opt 0 /proc 260K /r…...

丰田工厂停产竟然因为磁盘...

丰田因磁盘空间不足关闭14家工厂 在如今的信息时代,无论是生活还是工作,我们都离不开计算机和网络。然而,令人惊讶的是,一家全球知名的汽车制造商——丰田,却因为磁盘空间不足的问题,被迫关闭了14家工厂。…...

Python工程师Java之路(p)Maven聚合和继承

文章目录 依赖管理依赖传递可选依赖和排除依赖 继承与聚合 依赖管理 指当前项目运行所需的jar&#xff0c;一个项目可以设置多个依赖 <!-- 设置当前项目所依赖的所有jar --> <dependencies><!-- 设置具体的依赖 --><dependency><!-- 依赖所属群组…...

Java 复习笔记 - Lambda 表达式 he 经典算法题

文章目录 Lambda表达式 概述&#xff08;一&#xff09;基本作用&#xff08;二&#xff09;特点 一&#xff0c;初识Java中的Lambda 表达式二&#xff0c;函数式编程三&#xff0c;省略写法四&#xff0c;练习&#xff1a;使用Lambda 表达式 简化Comparator接口的匿名形式综合…...

算法——快乐数

202. 快乐数 - 力扣&#xff08;LeetCode&#xff09; 由图可知&#xff0c;其实这也是一个判断循环的过程&#xff0c;要用到快慢指针&#xff0c;且相遇后&#xff0c;若在全为1的循环里&#xff0c;那么就是快乐数&#xff0c;若相遇后不为1&#xff0c;说明这不是快乐数。 …...

vue使用window.location.href 跳转失败

问题&#xff1a; vue项目中直接使用window.lcocation.href跳转外链&#xff0c;但是跳转的链接会被拼接成这样 http://localhost:8080/#/www.baidu.com 原因&#xff1a; 我们打开的外部链接会自动拼接我们的源地址&#xff0c;导致网址链接不正确&#xff0c;无法正常访问 …...

【备忘】清理Office缓存

【背景】电脑安装了M365 Apps for enterprise的客户端&#xff0c;遇到不常见的奇怪问题。尝试看清理缓存是否可以解决。 【清理步骤】 1. 关闭所有Office365 应用&#xff1b; 2. 搜索 %AppData% &#xff0c;并打开该文件夹&#xff1b; 3. 进到 AppData > Local > M…...

MacOS环境变量source生效但重启后又失效

https://blog.csdn.net/dxk539687357/article/details/127942044 .bash_profile 和 .zshrc 都是macos系统重环境变量配置的文件&#xff0c;但是两者有不同之处。 .bash_profile&#xff1a;在执行source ~/.bash_profile&#xff0c;只在当前窗口生效&#xff0c;但关闭当前…...

Sql语句大全--插入

今天抽空整理下项目中的Sql语句 项目中用到的Sql语句大全 Insert 语句&#xff0c;有简有难 Insert 语句&#xff0c;有简有难 insert into clayor (pco,ppolnum,ptype,psn,prela,pname,pid,paddr1,paddr2,pbakcod1,pbakcod2,paccnum,pchkflag,pagtcod,pstatus, pchksts,pauth…...

Unity 收取“运行费”引众怒,开源免费3D游戏引擎CGE(Castle Game Engine)吸引开发者关注

特征 1. 总结2. 跨平台3. 可视化编辑器4.视口与场景&#xff0c;相机&#xff0c;导航和其他组件5. 数据格式 5.1. glTF5.2. X3D5.3. 精灵表5.4. 脊柱6. 图形效果7. 图片8. 用户界面组件 8.1. 文本和字体9. 网络10. 优化和分析11. 声音12. 物理13. 平铺集成14. 粒子15. 使用现代…...

Apache DolphinScheduler - 快速扩展 TaskPlugin 从入门到放弃

目前在大数据生态中&#xff0c;调度系统是不可或缺的一个重要组件。Apache DolphinScheduler 作为一个顶级的 Apache 项目&#xff0c;其稳定性和易用性也可以说是名列前茅的。而对于一个调度系统来说&#xff0c;能够支持的可调度的任务类型同样是一个非常重要的因素&#xf…...

线性代数的本质(四)——行列式

文章目录 行列式二阶行列式 n n n 阶行列式行列式的性质克拉默法则行列式的几何理解 行列式 二阶行列式 行列式引自对线性方程组的求解。考虑两个方程的二元线性方程组 { a 11 x 1 a 12 x 2 b 1 a 21 x 1 a 22 x 2 b 2 \begin{cases} a_{11}x_1a_{12}x_2b_1 \\ a_{21}x_…...

适合初学者快速入门的Numpy实战全集

适合初学者快速入门的Numpy实战全集 Numpy是一个用python实现的科学计算的扩展程序库&#xff0c;包括&#xff1a; 1、一个强大的N维数组对象Array&#xff1b;2、比较成熟的&#xff08;广播&#xff09;函数库&#xff1b;3、用于整合C/C和Fortran代码的工具包&#xff1b…...

rabbitmq 面试题

1.交换机类型 RabbitMQ是一个开源的消息队列系统&#xff0c;它支持多种交换机类型&#xff0c;用于在消息的生产者和消费者之间路由和分发消息 Direct Exchange&#xff08;直接交换机&#xff09;&#xff1a;Direct交换机是最简单的交换机类型之一。它将消息按照消息的Rout…...

比较Visual Studio Code中的文件

目录 一、比较两个文件 1.1VS code中的文件大致分为两类&#xff1a; 1.2如何比较VS code中的两个文件&#xff1f; 二、并排差异模式&#xff1a;VS code中的一种差异模式 三、内联差异模式&#xff1a;VS code中的另一种差异模式 四、VS code忽略在行首或者行尾添加或删除…...

誉天在线项目-UML状态图+泳道图

什么是UML UML&#xff08;Unified Modeling Language&#xff09;是一种用于软件系统建模的标准化语言。它提供了一组图形符号和规范&#xff0c;用于描述和设计软件系统的结构、行为和交互。 UML图形符号包括类图、用例图、时序图、活动图、组件图、部署图等&#xff0c;每…...

【linux基础(六)】Linux中的开发工具(中)--gcc/g++

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到开通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux中的开发工具 1. 前言2.…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

一些实用的chrome扩展0x01

简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序&#xff0c;无论是测试应用程序、搜寻漏洞还是收集情报&#xff0c;它们都能提升工作流程。 FoxyProxy 代理管理工具&#xff0c;此扩展简化了使用代理&#xff08;如 Burp…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...