位置: IT常识 - 正文

Promise的九大方法(resolve、reject、then、catch、finally、all、allSettled、race、any)你都用过那些?(promise的几种状态)

编辑:rootadmin
Promise的九大方法(resolve、reject、then、catch、finally、all、allSettled、race、any)你都用过那些?

推荐整理分享Promise的九大方法(resolve、reject、then、catch、finally、all、allSettled、race、any)你都用过那些?(promise的几种状态),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:promise的方法有哪些,“promise”,promise有几种方法,promise常用方法,promise的方法有哪些,promise都有什么意思,promise有几种方法,promise有几种方法,内容如对您有帮助,希望把文章链接给更多的朋友!

前言:

        定期复盘---今天我们来复习一下 Promise 的几个方法,分别是:Promise.resolve、Promise.reject、Promise.then、Promise.catch、Promise.finally、Promise.all、Promise.allSettled、Promise.race、Promise.any;

        接下来我们一起去看看吧,从深处去了解他们有什么区别!!!

目录

Promise 状态

1. Promise.resolve

2. Promise.reject

3. Promise.then

  ① 函调函数异步执行

  ② 返回值   

  ③ promise穿透

4. Promise.catch

  ① 语法糖的本质

  ② 只有一个主人

5. Promise.finally

6. Promise.all

7. Promise.allSettled

8. Promise.race

9. Promise.any


Promise 状态

初始状态 -> pending初始状态可以改变在resolve 或者 reject 调用之前都处于这个状态最终成功状态 -> fulfilled执行 resolve 函数,状态改变为 fulfilled执行 onFulfilled 函数最终失败状态 -> rejected执行 reject 函数,状态改变为 rejected执行 onRejected 函数then 方法then 方法为 Promise 对象注册了 onFulfilled 和 onRejected 函数catch 方法catch 方法为Promise 对象注册了 onRejected 函数1. Promise.resolve

    静态方法 Promise.resolve(value)可以认为是 new Promise方法的语法糖,比如Promise.resolve(42) 可以认为是以下代码的语法糖。

new Promise(function (resolve) { resolve(42)})

     这个静态方法会让Promise对象立即进入确定(即resolved) 状态,并将42传递给后面 then 里所指定的 onFulfilled函数。作为 new Promise的快捷方式,在进行 Promise 对象的初始化或者编写测试代码的时候都非常方便。

      简单总结一下 Promise.resolve方法的话,它的作用就是将传递给它的参数填充 Fulfilled 到 Promise 对象后并返回这个 Promise 对象。

2. Promise.reject

  Promise.reject(error)是和Promise.resolve(value)类似的静态方法,是 new Promise 方法的快捷方式。比如 Promise.reject(new Error("Promise reject error")) 就是下面代码的语法糖形式

new Promise(function (reject) { reject(new Error("Promise reject error"))})

      简单总结一下 Promise.reject方法的话:它的功能是调用该 Promise对象通过then指定的 onRejected函数,并讲错误(Error)对象传递给这个onRejected函数

3. Promise.then

    Promise.then(onFulfilled, onRejected)

  ① 函调函数异步执行var promise = new Promise((resolve, reject) => { console.log("inner Promise"); // 1 setTimeout(() => { resolve("Fashion Barry"); // 3 }, 1000);});promise.then((res) => { console.log("res", res);});console.log("outer promise"); // 2// Promise 实际是一个同步函数,then 方法才是异步// 所以输出顺序如上

  Promise/A+规范统一规定:Promise 只能使用异步调用方式

  ② 返回值   

    不管你在回调函数 onFulfilled中会返回一个什么样的值,或者不返回值,该值都会由 Promis.resolve(return 的返回值) 进行响应的包装处理。因此,最终 then的结果都是返回一个新创建的 Promise对象。

    也就是说,Promis.then不仅仅是注册一个回调函数那么简单,它还会将回调函数的返回值进行变换,创建并返回一个Promise 对象。正是 then函数中有了这样返回值的机制,才能使得在整个Promise链式结构当中,每个then方法都能给 下一个then方法传递参数。现在我们知道怎么返回的Promise是之前的还是新的?另外该Promise的状态又是如何?

var aPromise = new Promise((resolve, reject) => { resolve("aPromise");});var thenPromise = aPromise.then((res) => { console.log("thenPromise: ", res);});var catchPromise = aPromise.catch((err) => { console.error("catchPromise: ", err);});console.log(aPromise !== thenPromise); // trueconsole.log(thenPromise !== catchPromise); // trueconsole.log(aPromise, thenPromise, catchPromise); // Promise { "aPromise" }, Promise { <pending> }, Promise { <pending> }

    从上面结果来看,实际上不管是调用 then还是catch方法, 都返回了一个新的Promise对象

  ③ promise穿透

   我们先来举个例子:

Promise.resolve("Barry").then(Promise.resolve("Barry Promise")).then((result) => { console.log("result", result); // "Barry"});

如果你认为输出的是【 Barry Promise 】,那么你就错了,实际上他输出的是 【 Barry 】

产生这么的输出是因为你给then方法传递了一个非函数(比如promise对象)的值,代码会这样理解 : then(null),因此导致了前一个promise的结果产生了坠落的效果,也就是和下面代码是一样的, 代码直接穿透了then(null)进入了下一层链:

Promise.resolve("Barry").then(null).then((result) => { console.log("result", result); // "Barry"});

随意添加多个then(null)结果都是一样的

Promise.resolve("Barry").then(null).then({ name: "My name is Barry" }).then(null).then((result) => { console.log("result", result); // "Barry"});4. Promise.catch  ① 语法糖的本质Promise的九大方法(resolve、reject、then、catch、finally、all、allSettled、race、any)你都用过那些?(promise的几种状态)

        这里我们再说一遍,实际上Promise.catch只是promise.then(undefined, onRejected) 方法的一个别名而已。也就是说,这个方法用来注册当Promise对象状态变为 Rejected时 的回调函数。可以看下面代码,两者写法是等价的,但是很明显 Promise.catch会让人第一眼看上去不会眼花缭乱:

// 第一种写法Promise.resolve() .then((data) => console.log(data)) .then(undefined, (err) => console.log(err));// 第二种写法Promise.resolve() .then((data) => console.log(data)) .catch((err) => console.log(err));

那么我们现在来说说为什么推荐使用第二种方法,而不是第一种:

使用promise.then(onFulfilled, onRejected) 的话,在onFulfilled中发生异常的话,onRejected 中是捕获不到这个异常的。而且如果链式很长,每一条链上都要这么写。在promise.then(onFulfilled).catch(onRejected) 的情况下.then中产生异常能在.catch 中捕获。.then和.catch本质上是没有区别的, 需要分场合使用  ② 只有一个主人

        我们上面已经说过了,在书写很长的Promise链式,从代码清晰度和简易程度来讲,在最后添加 catch是远远在每一层链上写onRejected回调函数是要好的,因为catch可以捕获 Promise链中每一层节点的错误,这句话本身没有错,但从这句话延伸出一种错误的理解:catch 同时监控着所有节点。实际上catch函数在同一个时间点只属于某一个Promise,因为它的主人是随着程序 的执行而不断变化的,我们来举个例子:

let p1 = new Promise((resolve, reject) => { // 第一层执行逻辑 resolve("first promise"); // Promise(1)}) .then((res) => { // 第二层执行逻辑 return "second promise"; // Promise(2) }) .then((res) => { // 第三层执行逻辑 return "third promise"; // Promise(3) }) .catch((err) => { console.log("err", err); });

在上述例子中,如果整个程序每一步都正确执行,那么会顺序产生三个Promise对象,分别是 Promise(1),Promise(2),Promise(3):

可是如果在第一层具体执行逻辑出错了后,那实际上后面的两个then 中的回调函数压根不会被异步执行,所以会直接异步触发catch中的回调函数执行, 所以这种情况下catch是Promise(1)对象的catch。如果第一层具体执行逻辑正确执行,就会异步触发第二个then中的回调函数执行,那么同理 ,在第二次具体执行逻辑抛出错误,会导致Promise(2)的状态变化,所以这种情况下catch 是Promise(2)对象的catch。同理Promise(3)也是如此

总结下来就是:整个Promise链中,catch只属于异步触发它当中回调函数 执行的那个Promise,并不属于所有 Promise

5. Promise.finally

    promise.finally方法的回调函数不接受任何参数,这意味着finally没有办法 知道,前面的Promise状态到底是fulfilled还是rejected 。这表明,finally方法里面的操作,应该是与Promise状态无关的,不依赖于 Promise的执行结果。我们来看下面代码:

var p1 = new Promise((resolve, rejevt) => { setTimeout(() => { resolve; }, 1000);});p1.then((res) => console.log(res)) .catch((err) => console.log(err)) .finally(() => console.log("finally"));

finally本质上是then方法的特例。我们来看下面伪代码:

promise.finally(() => { // 执行逻辑});// 上面代码等同于下面promise.then( (onFulilled) => { // 语句 return onFulilled; }, (onRejected) => { // 语句 throw onRejected; });

上面代码中,如果不使用finally方法,同样的语句需要为成功和失败的状态各写一次。 有了finally方法,则只需要写一次。那么它是如何实现的呢?

Promise.prototype.finally = function (callback) { let p = this.constructor; return this.then( (value) => p.resolve(callback()).then(() => value), (reason) => p.reject(callback()).then(() => { throw reason; }) );};var p = new Promise((resoleve, reject) => { setTimeout(() => { reject("Promise err"); }, 1000);});p.catch((err) => console.log("err", err)).finally(() => { console.log("finally");});

上述代码中,不管前面的Promise是fulfilled还是rejected ,都会执行回调函数callback

6. Promise.all

    Promise.all接受一个promise对象的数组作为参数,当这个数组里的所有 Promise 对象 全部变为resolve或者reject状态的时候,它才会去调用.then方法。

    传递给Promise.all的 promise并不是一个个的顺序执行的,而是同时开始、并行执行的,我们可以看下面例子

var promise1 = new Promise((resoleve, reject) => { setTimeout(() => { resoleve("promise1--3000"); }, 3000);});var promise2 = new Promise((resoleve, reject) => { setTimeout(() => { resoleve("promise2--1000"); }, 1000);});var promise3 = new Promise((resoleve, reject) => { setTimeout(() => { resoleve("promise3--5000"); }, 5000);});var promiseArr = [promise1, promise2, promise3];console.time("promiseArr");Promise.all(promiseArr) .then((res) => { console.log("res", res); // ['promise1--3000', 'promise1--1000', 'promise1--5000'] console.timeEnd("promiseArr"); // 5523.29296875 ms }) .catch((err) => console.log(err));

为什么这个例子可以看出来Promise.all()是并行的呢?因为所有Promise执行完只用了5秒,如果3个 Promise是按照顺序执行的,那么应该是9秒或者,在5-9之间,因为4个Promise并不是同时执行的,同时执行的 话总时间就是那个花费时间最长的Promise

Promise.all()重要细节点 (面试常考):

如果所有的Promise中只有一个执行错误,那么整个Promise.all不会走Promise.all().then() 而是走Promise.all().catch()这个流程了。但是要注意的是虽然走到了Promise.all().catch()这个流程 ,但是其他 Promise 还是会正常执行,但不会返回结果要注意Promise.all()的返回值顺序,Promise.all().then()的返回值顺序和传入的顺序是一致的,笔试时 遇到手写Promise.all()时要注意。7. Promise.allSettled

  Promise.allSettled()的入参和Promise.all、Promise.race一样,接受一个promise 对象的数组作为参数,也是同时开始、并行执行的。但是Promise.allSettled的返回值需要注意以下几点:

Promise.allSettled不会走进catch,当所有输入Promise都被履行或者拒绝时, statusesPromise 会解析一个具有具体完成状态的数组

{ status: 'fulfilled', value:value } :如果相应的promise被履行{ status: 'rejected', reason: reason }:如果相应的promise被拒绝

我们看下面示例:

var promise1 = new Promise((resoleve, reject) => { setTimeout(() => { reject(new Error("promise1--3000")); // resoleve("promise1--3000"); }, 3000);});var promise2 = new Promise((resoleve, reject) => { setTimeout(() => { // reject(new Error("promise1--1000")) resoleve("promise2--1000"); }, 1000);});var promise3 = new Promise((resoleve, reject) => { setTimeout(() => { resoleve("promise3--5000"); // reject(new Error("promise1--5000")) }, 5000);});var promiseArr = [promise1, promise2, promise3];console.time("promiseArr");Promise.allSettled(promiseArr) .then((res) => { console.log("res", res); console.timeEnd("promiseArr"); }) .catch((err) => console.error(err)) .finally(() => console.log("finally"));

总结一下:Promise.allSettled()在你需要执行平行和独立的异步操作并收集所有结果时非常有效, 即使某些异步操作可能失败。

8. Promise.race

  Promise.rece()的使用方法和 Promise.all一样,接收一个promise 对象的数组为参数,Promise.race是要有一个promise对象进入Fulfilled或者 Rejected状态的话,就会继续进行后面的处理。这里依旧有两个点要注意:

和Promise.all一样是所有数组当中的Promise同时并行的Promise.race 在第一个Promise对象变为Fulfilled之后,并不会 取消其他promise对象的执行。Promise.race接受的是一个Promise对象数组,但是返回的确实最先完成Fulfilled 或者最先被Rejected的一个Promise的结果

下面我们来举个例子:

let arr = [1000, 3000, 5000, 7000];let promiseArr = [];for (let i = 0; i < arr.length; i++) { let newPromise = new Promise((resolve, reject) => { if (i === 0) { reject(new Error("第二个错误")); } else { setTimeout(() => { console.log(arr[i]); resolve(arr[i]); }, arr[i]); } }); promiseArr.push(newPromise);}Promise.race(promiseArr) .then((res) => { console.log(res); }) .catch((err) => { console.log(err); });// 控制台报错// 3000// 5000// 7000

这里我们再复习一下Node当中事件循环的知识:

第一层循环:i为0时,异步触发了Promise.race().catch(),这里面的回调代码被放在了微任务队列中, 后面的3个setTimeout宏任务的回调函数代码被放进了timer阶段中的队列当中(其实并不是这样,因为 三个定时器都有延迟,都是在后面的事件循环中添加进来的)第二层循环:清空微任务对列,所以控制台打印出了错误,然后清空宏任务,分别打印出3000/5000/70009. Promise.any

  Promise.any的入参和Promise.all、Promise.race、Promise.allSettled一样, 接收一个promise对象的数组作为参数。

只要其中有一个Promise成功执行,就会返回已经成功执行的Promise的结果如果这个promise对象的数组中没有一个promise 可以成功执行(即所有的 promise都失败 ),就返回一个失败的promise 和AggregateError类型的实例,它是Error的一个子类,用于把单一的错误集合 在一起var promise1 = new Promise((resoleve, reject) => { setTimeout(() => { // reject(new Error("promise1--3000")); resoleve("promise1--3000"); }, 3000);});var promise2 = new Promise((resoleve, reject) => { setTimeout(() => { // reject(new Error("promise2--1000")) resoleve("promise1--1000"); }, 1000);});var promise3 = new Promise((resoleve, reject) => { setTimeout(() => { // resoleve("promise3--5000"); reject(new Error("promise1--5000")) }, 5000);});var promiseArr = [promise1, promise2, promise3];console.time("promiseArr");Promise.any(promiseArr) .then((res) => { console.log("res", res); // res promise1--1000 console.timeEnd("promiseArr"); }) .catch((err) => console.error(err)); //所有的Promise都失败, AggregateError: All promises were rejected

总计一下Promisea.any的应用场景:如果我们现在有多台服务器,则尽量使用响应速度最快的服务器,在这种情况下, 可以使用Promise.any()方法从最快的服务器接收响应。

本文链接地址:https://www.jiuchutong.com/zhishi/300162.html 转载请保留说明!

上一篇:HTML+CSS+JS 学习笔记(一)———HTML(中)(html/css/javascript标准教程)

下一篇:Vue懒加载(vue懒加载机构树刷新)

  • 做好SEO博客要注意的六种方法 (做好seo博客要注意什么)

    做好SEO博客要注意的六种方法 (做好seo博客要注意什么)

  • 央视频可以回看吗(央视频可以回看世界杯吗)

    央视频可以回看吗(央视频可以回看世界杯吗)

  • 抖音亲密值一天可以升多少(抖音亲密值一天200就不涨)

    抖音亲密值一天可以升多少(抖音亲密值一天200就不涨)

  • 极米h3为什么没镜头盖(极米h 3 s)

    极米h3为什么没镜头盖(极米h 3 s)

  • 快手设置里没有实验室怎么回事(快手设置里没有大屏模式怎么办)

    快手设置里没有实验室怎么回事(快手设置里没有大屏模式怎么办)

  • soul被限制群聊是什么意思(soul限制群聊几天)

    soul被限制群聊是什么意思(soul限制群聊几天)

  • qq群不小心解散了该怎么恢复(qq群不小心解散了还能恢复吗)

    qq群不小心解散了该怎么恢复(qq群不小心解散了还能恢复吗)

  • 计算机的特征有(计算机特征是什么)

    计算机的特征有(计算机特征是什么)

  • 三星fold支持5g吗(三星fold支持25w快充吗)

    三星fold支持5g吗(三星fold支持25w快充吗)

  • vivos6cpu型号(vivos6是什么处理器)

    vivos6cpu型号(vivos6是什么处理器)

  • 现代计算机的特点包括哪些(现代计算机的特点(简答题))

    现代计算机的特点包括哪些(现代计算机的特点(简答题))

  • 10gbps是几兆网速(10mbps是多少网速)

    10gbps是几兆网速(10mbps是多少网速)

  • gp alkaline 能充电吗(gp supercell 是否可以充电)

    gp alkaline 能充电吗(gp supercell 是否可以充电)

  • 空气净化器能开一夜吗(空气净化器能开多久)

    空气净化器能开一夜吗(空气净化器能开多久)

  • 哔哩哔哩的视频怎么下载到本地(哔哩哔哩的视频怎么保存到电脑)

    哔哩哔哩的视频怎么下载到本地(哔哩哔哩的视频怎么保存到电脑)

  • pe-tl20是什么型号(petl10)

    pe-tl20是什么型号(petl10)

  • 苹果a1932是什么型号(苹果a1932是哪款)

    苹果a1932是什么型号(苹果a1932是哪款)

  • 蓝牙耳机会致癌吗(蓝牙耳机会得癌症吗)

    蓝牙耳机会致癌吗(蓝牙耳机会得癌症吗)

  • 苹果通知和状态栏在哪(苹果通知和状态栏的设置)

    苹果通知和状态栏在哪(苹果通知和状态栏的设置)

  • ios实况图怎么发给别人(iphone 实况照片怎么发)

    ios实况图怎么发给别人(iphone 实况照片怎么发)

  • pdf格式是什么(pdf格式是什么软件)

    pdf格式是什么(pdf格式是什么软件)

  • 找抖音的人工服务(抖音人工服务中心电话)

    找抖音的人工服务(抖音人工服务中心电话)

  • 路由器的5g和2.4g是什么意思(路由器的5g和2.4g游戏有什么区别)

    路由器的5g和2.4g是什么意思(路由器的5g和2.4g游戏有什么区别)

  • qq达人什么时候开始的(qq达人什么时候出来的)

    qq达人什么时候开始的(qq达人什么时候出来的)

  • (区别、详解、使用)module.exports与exports,export与export default,import 与require(建造师与建筑师的区别详解)

    (区别、详解、使用)module.exports与exports,export与export default,import 与require(建造师与建筑师的区别详解)

  • 蓝桥杯第十四届蓝桥杯模拟赛第三期考场应对攻略(C/C++)(蓝桥杯第十四届模拟赛第三期)

    蓝桥杯第十四届蓝桥杯模拟赛第三期考场应对攻略(C/C++)(蓝桥杯第十四届模拟赛第三期)

  • 给织梦DedeCMS文章标题增加自动加长尾关键词的方法(织梦添加文章如何修改高级参数)

    给织梦DedeCMS文章标题增加自动加长尾关键词的方法(织梦添加文章如何修改高级参数)

  • 企业所得税年报申报时间
  • 税收工资什么意思
  • 以前年度损益调整在借方是什么意思
  • 利润分配转作股本股利
  • 邯郸银行公对公转账时间
  • 境内货代公司之间付美金
  • 企业销售货物收入没有银行流水
  • 企业将存货低价出售处理要如何做会计处理?
  • 营改增各项业务销售额按照什么确定
  • 电费发票勾选是啥意思
  • 租赁合同印花税计税依据
  • 企业当年度增值税税率
  • 刷银行卡消费安全吗
  • 顾问费的个税怎么扣
  • 房地产公司销售自建房怎么纳税
  • 小规模纳税人购车好处
  • 免费样品销售给客户计入什么科目
  • 费用提多了利润少了所得税是如何调整?
  • 多交的公积金怎么退回来
  • 增值税谁来付
  • 苹果14promax价格
  • win10专业版分辨率1920x1080不见了
  • 只交社保不发工资可以吗
  • 小企业会计准则和一般企业会计准则的区别
  • 营业外支出的核算内容包括
  • win10怎么关掉
  • 银行初级证书全称
  • 安装win7系统的硬件要求
  • linux tr
  • wind10画图在哪
  • 境外代扣代缴企业所得税的计税依据包含企业所得税嘛
  • 清算期间会计分录
  • nginx反向代理未知域名
  • html怎么嵌套php
  • PHP用mysql_insert_id()函数获得刚插入数据或当前发布文章的ID
  • node更新到最新版本
  • html写php
  • php 引用
  • 企业改制资产整合过程中涉及的土地增值税
  • 现金流量表填写说明
  • 金蝶财务软件系统要求
  • 新公司开账户需要多少钱
  • 罚款支出计入什么费用
  • 网银数字证书年费
  • mysql视图菜鸟教程
  • 新会计准则股权投资
  • 发行股票的好处和坏处
  • 差旅费中火车票的进项税怎么计算
  • 电影院租金一般多少为合理
  • 原材料贷方余额怎么转成本
  • 房产税怎么实行
  • 收购股权如何做分录
  • 土地使用权出资是什么意思
  • 上月有留底税额时本月缴纳税款时怎么做分录
  • 会计一般采用什么科目
  • 进入四大会计师事务所怎么样
  • MySQL下载安装步骤详解
  • mysql在本地主机创建用户账号
  • window系统大全
  • window10的dns异常
  • 如何去掉windows7开机密码
  • centos7安装MySQL8.0
  • linux php教程
  • windows7磁盘清理命令
  • ExtJS 2.0实用简明教程 之Border区域布局
  • android开发webview
  • cocos2dx适配
  • 阴影效果有什么用
  • shell脚本echo输出变量
  • java框架怎么用
  • centos 设置定时任务执行指定脚本的方法
  • float浮动布局原理
  • 深入理解javascript特性
  • jquery中的动画方法有哪些
  • javascript中的函数该如何理解
  • pip install clashroyale
  • jquery网页
  • 建行信用卡怎么提额
  • 沈阳税务机关地区编号
  • 如何查询公司是一般纳税人还是小规模纳税人
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设