ES6 - promise.all和race方法的用法详解

news2024/9/29 9:36:02

在这里插入图片描述

文章目录

      • 一、前言
      • 二、`Promise.all()`
        • 1,第一句:Promise.all()方法接受一个数组作为参数,且每一个都是 Promise 实例
        • 2,第二句:如果不是,就会先调Promise.resolve方法,将参数转为 Promise 实例再进一步处理
        • 3,第三句:Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例
      • 三、`Promise.race()`
      • 四、总结

一、前言

谈谈你对Promise的理解?

:Promise用来解决异步回调问题,由于js是单线程的,很多异步操作都是依靠回调方法实现的,这种做法在逻辑比较复杂的回调嵌套中会相当复杂;也叫做回调地狱;

promise用来将这种繁杂的做法简化,让程序更具备可读性,可维护性;promise内部有三种状态,pending,fulfilled,rejected;pending表示程序正在执行但未得到结果,即异步操作没有执行完毕,fulfilled表示程序执行完毕,且执行成功,rejected表示执行完毕但失败;这里的成功和失败都是逻辑意义上的;并非是要报错。其实,promise和回调函数一样,都是要解决数据的传递和消息发送问题,promise中的then一般对应成功后的数据处理,catch一般对应失败后的数据处理。

(1) All方法

他是Promise对象中的方法 他是一次执行多个promise;

(2) race方法

他也是Promise对象中的方法 他是执行最快的那个promise;All方法可以触发多个 ,他只是触发一个 但是在多个promise中做出一个选择,选择出一个运行最快的promise;

二、Promise.all()

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

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

上面代码中,Promise.all()方法接受一个数组作为参数,p1p2p3都是一个 Promise 实例,如果不是,就会先调Promise.resolve方法,将参数转为 Promise 实例再进一步处理。另外,Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。

该怎么理解这句话呢,下面将逐句说明;

1,第一句:Promise.all()方法接受一个数组作为参数,且每一个都是 Promise 实例

这句话说明了 Promise的标准用法:

即传入一个数组,期望数组里面的每一项都是一个promise实例;如下使用:

	 ## 1,先定义几个异步函数,此处用定时器 
      let p1 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_1");
        }, 1000);
      });
      let p2 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_2");
        }, 2000);
      });
      let p3 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_3");
        }, 3000);
      });
      
	## 2,使用
	Promise.all([p1, p3, p2])
        .then((result) => {
          console.log(result); // 结果为:['success_2', 'success_3', 'success_1']
        })
        .catch((error) => {
          console.log(error); 
        });

等待几秒后,结果打印为:

['success_2', 'success_3', 'success_1']

Promise.all接收到的数组顺序是一致的,即p3的结果在p2的前面,即便p3的结果获取的比p2要晚;这带来了一个很大的好处;

在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用Promise.all毫无疑问可以解决这个问题;


Promise.all 里面所有的promise都执行成功(fulfilled状态)才会返回成功的数组,只要有一个失败(reject),就会被catch回调捕获;如下失败的情况:

 	 let p1 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_1");
        }, 1000);
      });
      let p2 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_2");
        }, 2000);
      });
      ## 1,失败的promsie
      let p3 = Promise.reject("失败");
      
      	## 2,执行
  		 Promise.all([ p1,p2,p4])
        .then((result) => {
          console.log(result);
        })
        .catch((error) => {
          console.log("error:",error); // 失败了,打印 '失败'
        });

执行结果如下:

error:失败

说明只要其中有一个失败就返回失败数据;

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

请务必记住:promise.all 接收的promise数组,是按顺序且同步执行的


2,第二句:如果不是,就会先调Promise.resolve方法,将参数转为 Promise 实例再进一步处理

如果我们传入的数组项不是promsie对象,还会正常执行吗:

(1):传入的数组每一项都不是 promise实例

		## 直接传 几个number类型
  		Promise.all([1, 2, 3])
        .then((res) => {
          console.log("res:", res); // [1,2,3]
        })
        .catch((err) => {
          console.log("err:", err);
        });

执行结果:

[1,2,3]

可以看出:如果传入数组中的每一项都不是 promise对象 则会原封不动的让 resolve()函数返回 ;
既拿到什么就返回什么;

(2)第二种:传入的数组中既有promise实例 也有不是的

如下:我传了number 1,2 和两个promise实例 p2,p1;

     let p1 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_1");
        }, 1000);
      });
      let p2 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_2");
        }, 2000);
      });
      
    Promise.all([1, 2, p2, p1])
        .then((res) => {
          console.log("res——2:", res); //  [1, 2, 'success_2', 'success_1']
        })
        .catch((err) => {
          console.log("err:", err);
        });

执行结果:

 [1, 2, 'success_2', 'success_1']

可以看出:执行的顺序是先返回非promise, 再执行p2,p1这两个promise对象,然后也按照顺序并返回结果;


3,第三句:Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例

怎么理解这句话呢,说明all方法传入的不一定是数组,还可能是支持遍历(Iterator)的其他数据结构;那这个数据结构不就是ES6新增的 Set集合吗;

概述Set集合

Set也是ES6的数据结构。特点是无序不重复,它类似于数组,但是成员的值都是唯一的,没有重复的值。Set本身是一个构造函数,用来生成Set数据结构,Set函数可以接受一个数组作为参数,用来初始化。

使用Promise.all()传入Set集合:

      let p1 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_1");
        }, 1000);
      });
      let p2 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_2");
        }, 2000);
      });
      let p3 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_3");
        }, 3000);
      });
	
	 ## 1,定义Set集合
	 let myMap = new Set([p2, p1, p3]); 
   	 console.log("myMap:", myMap); // Set(3) {Promise, Promise, Promise}

	## 2,all方法传入Set集合
      Promise.all(myMap)
        .then((myMapRes) => {
          console.log("myMapRes:", myMapRes); //   ['success_2', 'success_1', 'success_3']
        })
        .catch((err) => {
          console.log("err:", err);
        });

执行结果:

['success_2', 'success_1', 'success_3']

可以看出,执行的结果是和数组的方式是一样的;

三、Promise.race()

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

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

Promise.race是赛跑的意思,也就是说Promise.race([p1, p2, p3])里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败。

使用场景:

有时我们比如说有好几个服务器的好几个接口都提供同样的服务,我们不知道哪个接口更快,就可以使用Promise.race,哪个接口的数据先回来我们就用哪个接口的数据;

代码如下:

      let p1 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_1");
        }, 1000);
      });
      let p2 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_2");
        }, 2000);
      });
      let p3 = new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve("success_3");
        }, 3000);
      });
		
		## 调用race方法
        Promise.race([p2,p1,p3]).then(res=>{
          console.log("resRace:",res); // resRace: success_1
        }).catch(err=>{
          console.log("errRace:",err);
        })

执行结果:

resRace: success_1

p1确实是执行最快的,返回执行最快的那个promsie的resolve结果,其他的promsie将不会再管了;

当然,如果最快的这个执行promsie失败了,也是会走catch回调的;

四、总结

  1. promise.all 接收的promise数组,总是按顺序且同步执行并返回的;只要有一个promise失败,最终状态就是失败的(reject)就会被catch捕获。
  2. promise.race 也接收promise数组,总是返回执行最快的那一个,其他promise的状态并不关心。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/804375.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python web实战 | Docker+Nginx部署python Django Web项目详细步骤【干货】

概要 在这篇文章中,我将介绍如何使用 Docker 和 Nginx 部署 Django Web 项目。一步步讲解如何构建 Docker 镜像、如何编写 Docker Compose 文件和如何配置 Nginx。 1. Docker 构建 Django Web 项目 1.1 配置 Django 项目 在开始之前,我们需要有一个 D…

自定义代理

以下代码:可以在view 和model文章中进行添加 m_model new QStandardItemModel(2, FixedColumnCount, this);m_selection new QItemSelectionModel(m_model, this);ui->tableView->setModel(m_model); //设置模型ui->tableView->setSelectionModel(m_s…

第一堂棒球课:MLB棒球大联盟的主要战术·棒球1号位

MLB棒球大联盟的主要战术 攻击战术run-and-foul(跑垒战术):以速度为优势,在适当的时机发动进攻,争取在一回合内完成得分。 grounder(阻截战术):队员在垒包之间阻止对手的跑垒和传球。…

eclipse 最新版没有navigator视图如何解决

使用project exploere视图可以显示类似navigator视图 1.显示project exploere视图 window---->show view --->project exploere 2.project exploere视图转换为类似navigator视图 第一步:点击视图右上角三个点或者倒三角,点击fiters and custom…

【java入门学习】

文章目录 java学习章节目录学习前的准备main函数怎么写?Java程序运行的步骤如何让代码运行起来?java程序由三部分构成:注释注释规范 标识符练习 总结 java学习章节目录 SE语法 初阶段主要来熟悉java的语法: 1.初始java 2.数据类型…

真正实现无人化自主管理的清洁机器人来了!涂鸦智能新方案为你解密

如果你观察家庭清洁电器的发展历程,可以发现这就是一部人类“偷懒”史,而有技术含量的“懒”,真的可以改变世界! 一、懒是产品创新的重要灵感来源 从洗衣机替代手洗,到扫地机器人帮助人们从繁琐的地面清洁中解脱&…

RL 实践(6)—— CartPole【REINFORCE with baseline A2C】

本文介绍 REINFORCE with baseline 和 A2C 这两个带 baseline 的策略梯度方法,并在 CartPole-V0 上验证它们和无 baseline 的原始方法 REINFORCE & Actor-Critic 的优势参考:《动手学强化学习》完整代码下载:7_[Gym] CartPole-V0 (REINFO…

复现YOLOv8改进最新MPDIoU:有效和准确的边界盒回归的损失,打败G/E/CIoU,效果明显!!!

MPDIoU: A Loss for Efficient and Accurate Bounding Box Regression 论文简介MPDIoU核心设计思路论文方法实验部分加入YOLOv5代码论文地址:https://arxiv.org/pdf/2307.07662.pdf 论文简介 边界盒回归(Bounding box regression, BBR)广泛应用于目标检测和实例分割,是目标…

详细介绍如何使用HuggingFace和PyTorch进行医学图像分割-附源码

医学图像分割是一种创新过程,使外科医生能够拥有虚拟的“X 射线视觉”。它是医疗保健领域非常有价值的工具,可提供非侵入性诊断和深入分析。考虑到这一点,在这篇文章中,我们将探索威斯康辛大学麦迪逊分校胃肠道图像分割Kaggle 挑战数据集。作为该项目的一部分,我们将使用 …

python核心-面向对象-三大特性-综合案例

# 定义三个类, 小狗, 小猫, 人 # 小狗: 姓名, 年龄(默认1岁); 吃饭, 玩, 睡觉, 看家(格式: 名字是xx, 年龄xx岁的小狗在xx) # 小猫: 姓名, 年龄(默认1岁); 吃饭, 玩, 睡觉, 捉老鼠(格式: 名字是xx, 年龄xx岁的小猫在xx) # 人: 姓名, 年龄(默认1岁), 宠物; 吃饭…

【替换】批量替换命令文件名称或者文件内容

你是否困扰过,每次文件F2进行修改,十几个没关系,百来个写代码麻烦,那就使用shell命令吧 执行语句 先养成习惯查询验证,因为是批量替换,为了防止全局替换嘎嘎叫 替换文件名 # 【习惯】先使用顾虑查询&…

暴力猴插件简明开发教程->百度首页默认设置为我的关注

文章目录 暴力猴插件开发简明教程->百度首页默认设置为我的关注缘起缘灭思路实现尾声 暴力猴插件开发简明教程->百度首页默认设置为我的关注 缘起 在我的百度首页有很多自己设置的导航链接(接近100个),里面放了我常用的网站, 如下图 但是最近一段时间, 我发现百度做了一…

算法38:反转链表

一、需求 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1] 示例 2: 输入:head [1,2] 输出:[2,1] 示例3&#xff…

电器水族设备加热器UL1018检测报告

UL1018---电气水族设备 适用范围:本标准要求适用于300V或以下,用于室内商业或家用的水族器材上的设备。如加热器、水泵、过滤器、反射器 电线支架等相似用途的产品。 本标准不包括: 不是和水族器材一起用的照明器或台子;水族容器 一、UL1018标准测试内…

R中无法安装GitHub包 | 花费大量时间的小小经验

写在前面 最近在安装R包时,遇到无法安装包的情况,然后自己就各种捣鼓。最后,R环境也会让自己弄崩,如果你遇到此情况R语言无法调用stats.dll的问题解决方案,可以参考我前面的方法捣鼓一下。 那么,这个推文也是记录自己…

【Golang】Golang进阶系列教程--为什么 Go 不支持 []T 转换为 []interface

文章目录 前言官方解释内存布局程序运行中的内存布局通用方法 前言 在 Go 中,如果 interface{} 作为函数参数的话,是可以传任意参数的,然后通过类型断言来转换。 举个例子: package mainimport "fmt"func foo(v inter…

2023年自然语言处理与信息检索国际会议(ECNLPIR 2023) | EI Compendex, Scopus双检索

会议简介 Brief Introduction 2023年自然语言处理与信息检索国际会议(ECNLPIR 2023) 会议时间:2023年9月22日-24日 召开地点:中国杭州 大会官网:ECNLPIR 2023-2023 Eurasian Conference on Natural Language Processing and Information Retr…

【GO】go语言入门实战 —— 命令行在线词典

文章目录 程序介绍抓包代码生成生成request body解析respond body完整代码 字节青训营基础班学习记录。 程序介绍 在运行程序的时候以命令行的形式输入要查询的单词,然后程序返回单词的音标、释义等信息。 示例如下: 抓包 我们选择与网站https://fany…

【Linux命令200例】用ln创建链接文件

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,2023年6月csdn上海赛道top4。 🏆本文已收录于专栏:Linux命令大全。 🏆本专栏我们会通过具体的系统的命令讲解加上鲜活的实操案例对各个命令进行深入…

【Linux下6818开发板(ARM)】在液晶屏上显示RGB颜色和BMP图片

(꒪ꇴ꒪ ),hello我是祐言博客主页:C语言基础,Linux基础,软件配置领域博主🌍快上🚘,一起学习!送给读者的一句鸡汤🤔:集中起来的意志可以击穿顽石!作者水平很有限,如果发现错误&#x…