promise的使用和实例方法
前言
异步,是任何编程都无法回避的话题。在promise出现之前,js中也有处理异步的方案,不过还没有专门的api能去处理链式的异步操作。所以,当大量的异步任务逐个执行,就变成了传说中的回调地狱。
function asyncFn(fn1, fn2, fn3) {setTimeout(() => {//处理第一个异步任务fn1()setTimeout(() => {//处理第二个异步任务fn2()setTimeout(() => {//处理第三个异步任务fn3()},2000)},2000)}, 2000)}function fn1(){console.log('执行1')}function fn2(){console.log('执行2')}function fn3(){console.log('执行3') }asyncFn(fn1, fn2, fn3)
如果按照这么执行的话,等fn1执行完毕之后,再执行fn2,fn2执行完毕之后再执行fn3,这里只是简单的一个console.log,如果是真实的业务逻辑,那这看着可就太痛苦了。
promise就是用来解决这种问题的。
Promise基础
三种状态
pending代表状态未确定
fulfilled代表成功
rejected代表失败
类似于薛定谔的猫,开箱之前处于一种未知状态,只要你开了,那要么生,要么死,不会再发生更改。
记住,promise的状态是单向流的,一旦变化,永远不会发生更改。
基本用法
promise是个什么,答曰:构造函数。
成功的逻辑
//成功的promiselet prmFn1 = new Promise((resolve,jeject)=>{setTimeout(()=>{//模拟执行一个很消耗时间的任务resolve('我是成功的值')},5000)})prmFn1.then(resolve=>{console.log(resolve) //5秒后输出:我是成功的值})

失败的逻辑
//失败的promiselet prmFn2 = new Promise((resolve,reject)=>{setTimeout(()=>{reject('我是失败的原因')},5000)})console.log(prmFn2,'失败任务还没有开始执行',prmFn2)prmFn2.then(resolve=>{//成功才回被调用},reject=>{console.log('失败了被调用',reject)console.log('失败任务处理完毕',prmFn2)})

这里发生了什么:
1.通过new Promise构造函数创建了一个promise函数,参数是一个函数。
2.这个函数有两个参数,一个是resolve函数,一个是reject函数,resolve代表异步任务成功需要调用的,reject函数代表异步任务失败了需要调用的。
3.promise创建了之后,会变成一个有状态的对象,这个对象内有一个属性then,then是一个函数,then函数中有两个参数,这两个参数都是函数,参数1一个是专门用来处理成功的,参数2专门用来处理失败情况的。
4.参数1函数的参数,就是在promise中resolve(value)中的value,参数2函数的参数,就是promise中reject(errorReason)中的errorReason。
感觉很绕是不是,这里就是函数式编程的经典范例,也是promise对于很多初级前端来说,很懵的地方。
解决方案:多学多练多理解
promise对象的方法
promise是一个构造函数,但是同时也是一个对象,这个对象中存在很多用于处理不同业务的方法,所以可以称promise为函数对象
resolve
定义成功后回调
//resolvePromise.resolve('成功值').then(res => {console.log(res, 'resolve的使用')})//等同于new Promise((resolve, reject) => {resolve('成功值')}).then(res => {console.log(res, 'resolve的使用')})

reject
定义失败后回调
//rejectPromise.reject('失败值').then(res => {console.log(res, '不会走成功')}, rej => {console.log(rej, '会走失败')})//等同于new Promise((resolve, reject) => {reject('失败值')}).then(res => {console.log(res, '不会走成功')}, rej => {console.log(rej, '会走失败')})

then
根据状态值进行异步处理
当一个promise执行到then的时候,说明这个promise对象的状态值已经确定了,也就是只要执行到then方法里面,就说明前面的异步执行完成了,你可以根据返回的状态值进行异步的操作了。
then方法是promise的核心方法。
then是一个函数,接受两个参数,这两个参数都是函数,参数一处理成功回调,参数2处理失败回调
上面的代码都已经演示了,这里就不写了
catch
promise内发生意外报错回调处理
let prm = new Promise((resolve, reject) => {let a = nullconsole.log(a.a)resolve('成功')})prm.then(res => {console.log(res, '进入then方法')}).catch(error => {console.log(error, '进入error')})

all
所有异步都执行完毕后得到结果
异步都成功
let prm1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('执行prm1成功')}, 3000)})let prm2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('执行prm2成功')}, 1000)})let prm3 = new Promise((resolve, reject) => {setTimeout(() => {resolve('执行prm3成功')}, 5000)})Promise.all([prm1, prm2, prm3]).then(res => {console.log(res, '三个都执行完毕')})

异步中有失败
let prm1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('执行prm1成功')}, 3000)})let prm2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('执行prm2成功')}, 1000)})let prm3 = new Promise((resolve, reject) => {setTimeout(() => {reject('执行prm3失败')}, 5000)})Promise.all([prm1, prm2, prm3]).then(res => {console.log(res, '三个都执行完毕--成功')}, rej => {console.log(rej, '三个都执行完毕--有不成功')})

allSettled
all方法能获取所有任务都成功之后的值,但是如果多个任务有成功有失败,就无法全部获取所有状态,但是allSettled可以做到
//allSettled方法let pr1 = new Promise((resolve,reject)=>{setTimeout(()=>{resolve('pr1成功')},2000)})let pr2 = new Promise((resolve,reject)=>{setTimeout(()=>{resolve('pr2失败')},3000)})let pr3 = new Promise((resolve,reject)=>{setTimeout(()=>{resolve('pr3成功')},3000)})Promise.allSettled([pr1,pr2,pr3]).then(res=>{console.log(res,'获取所有状态')})

race
获取多个异步中最先执行完毕的结果
成功的情况
//race方法let prm1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('执行prm1成功')}, 3000)})let prm2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('执行prm2成功')}, 1000)})let prm3 = new Promise((resolve, reject) => {setTimeout(() => {reject('执行prm3失败')}, 5000)})Promise.race([prm1, prm2, prm3]).then(res => {console.log(res, '成功逻辑')},rej => {console.log(rej, '失败逻辑')})

失败的情况
let prm1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('执行prm1成功')}, 3000)})let prm2 = new Promise((resolve, reject) => {setTimeout(() => {reject('执行prm2失败')}, 1000)})let prm3 = new Promise((resolve, reject) => {setTimeout(() => {reject('执行prm3失败')}, 5000)})Promise.race([prm1, prm2, prm3]).then(res => {console.log(res, '成功逻辑')},rej => {console.log(rej, '失败逻辑')})

any
有一个成功,就是成功。全都失败,就是失败
//any方法let pr1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('pr1成功')}, 2000)})let pr2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('pr2失败')}, 3000)})let pr3 = new Promise((resolve, reject) => {setTimeout(() => {resolve('pr3失败')}, 3000)})Promise.any([pr1,pr2,pr3]).then(res=>{console.log(res,'成功')})Promise.any([pr2,pr3]).then(res=>{console.log(res,'失败')})

finally
不管一个promise任务执行成功还是失败,执行完毕后都会进入这个方法
//finally方法//成功let prm4 = new Promise((resolve,reject)=>{setTimeout(()=>{resolve('成功的值')},2000)})prm4.then(res=>{console.log(res,'成功')}).finally(val=>{console.log(val,'finally方法')})//失败let prm5 = new Promise((resolve,reject)=>{setTimeout(()=>{reject('失败原因')},2000)})prm5.catch(rej=>{console.log(rej,'失败')}).finally(val=>{console.log(val,'finally方法')})

项目中实际应用和注意事项
在当今的前端项目中,基本不会说用不到promise的,最常见的还是前后端数据交互,例如axios,fetch等请求都是通过promise封装后的,返回的值都是promise。
在项目实际场景中,会出现promise的回调链,下一个结果依赖上一个结果的返回值,形成异步任务的依赖关系。开发者需要去处理一个比较重要的问题,叫做中断promise链
中断promise链
//层层依赖形成执行链Promise.resolve('初始化成功值').then(res => {return new Promise(resolve => {setTimeout(() => {console.log(res)resolve('第一层返回成功值')}, 2000)})}).then(res => {return new Promise(resolve => {setTimeout(() => {console.log(res)resolve('第二层返回成功值')}, 2000)})}).then(res => {return new Promise(resolve => {setTimeout(() => {console.log(res)resolve('第三层返回成功值')}, 2000)})})
效果如下

我们可以根据每个任务的结果值去判定业务逻辑,是否需要中断后续的执行链条
代码改造如下
//中断promise链Promise.resolve('初始化成功值').then(res => {return new Promise(resolve => {setTimeout(() => {console.log(res)// resolve('第一层返回成功值')resolve('中断标识')}, 2000)})}).then(res => {if(res ==='第一层返回值'){return new Promise(resolve => {setTimeout(() => {console.log(res)resolve('第二层返回成功值')}, 2000)})}else{console.log('进入中断链方法')//返回一个空的promise,就完成了中断return new Promise(()=>{})}}).then(res => {return new Promise(resolve => {setTimeout(() => {console.log(res)resolve('第三层返回成功值')}, 2000)})})

总结
三种状态:pending,fulfilled,rejected。分别代表待定,成功和失败。一旦修改,无法改变
九种方法:
resolve代表返回成功状态
reject代表返回失败状态
then是执行完毕进入的回调
catch是执行出错进入的回调
all代表全部成功,返回的是所有异步任务的成功值
allSettled代表全部执行完毕,即使不成功,也会返回全部异步任务的值
race代表获取先执行完毕的异步值
any代表有一个成功,就是成功。全都失败,就是失败
finnally代表你不管成功还是失败,都得来我这里。
实际应用:
多了去了,很多第三方包都会用到,前后端交互必备
中断执行链:
返回一个空的promise
相关文章:
promise的使用和实例方法
前言 异步,是任何编程都无法回避的话题。在promise出现之前,js中也有处理异步的方案,不过还没有专门的api能去处理链式的异步操作。所以,当大量的异步任务逐个执行,就变成了传说中的回调地狱。 function asyncFn(fn1, fn2, fn3) {setTimeout(() > {//处理第一个异步任务fn1…...
Visual Studio2022配置ReSharper C++ 常用设置
如需安装免费的可以在下面留言,看到即回复 文章目录 Visual Studio2022配置ReSharper C 常用设置配置Visual Studio2022,使其能够按回车进行补全配置ReSharper C 设置自动弹出配置ReSharper C 的快捷键ReSharper C 去掉注释拼写使用中文注释 如何关闭新版…...
论文解读类的公众号/知乎专栏,交给agent去做吧...
作者 | 二狗 大家好我是二狗,是夕小瑶科技说编辑部的一名作者。 我平时主要负责写AI资讯报道的文章。 大家知道,前阵子二狗我在「赛博马良」平台弄了个AI员工后每次都非常顺利地在第一时间精准抓到爆火的选题。 比如当时Sam Altman被开除的事件&…...
【学习笔记】Java函数式编程03 Stream流-终结操作
书接上回 3.3.3 终结操作 3.3.3.1 forEach 对集合的每一个元素进行处理 接触很多了不赘述 3.3.3.2 count 用来获取当前流中的元素的个数 比如,打印出所有作家的作品的总数 System.out.println(authors.stream().flatMap(author -> author.getBooks().stre…...
2024 Android保活总结
本文介绍的方案都是无需用户主动开启权限的。如果需要用户主动开启权限或者加白名单之类的话保活的意义就不大了,毕竟用户不大可能主动原因让app一直在后台运行 常规的方案 OnePixelActivity 1,监听SCREEN_OFF启动一个像素的Activity,灭屏…...
迅为RK3568开发板Ubuntu上使用串口调试
我们也可以在虚拟机的 Ubuntu 上使用调试串口。首先要参考 11 手册安装好 Ubuntu20.04。在 Ubuntu上可以安装多种串口工具,比如 minicom,picocom,kermit。本章节我们来介绍 minicom 的安装和使用。 输入以下命令安装 minicomapt-get install…...
【http】HTTP/1.0、HTTP/1.1和HTTP/2.0
✨ 专栏介绍 在当今互联网时代,计算机网络已经成为了人们生活和工作中不可或缺的一部分。而要实现计算机之间的通信和数据传输,就需要依靠各种网络协议来进行规范和约束。无论是浏览网页、发送电子邮件还是进行在线交流,都离不开各种各样的网…...
automkcert使用教程
我们在开发的时候往往需要https开启一些浏览器功能,比如摄像头、wss等,自己的云服务器申请证书一个是麻烦,一个是价格贵,这种情况下可以用自签名证书。但自签名证书下有不通用的特点,其他机器无法快速信任自己的网站,因…...
tekton 发布 kubernetes 应用
tekton 发布 kubernetes 应用 基于Kubernetes 服务部署 Tekton Pipeline 实例,部署完成后使用tekton来完成源码拉取、应用打包、镜像推送和应用部署。 本文实现一个 golang-helloworld 项目 CI/CD 的完整流程,具体包括以下步骤: 从 gitee…...
unity脚本API中OnCollisionEnter()、OnTriggerEnter()二者的区别
Unity中的OnCollisionEnter和OnTriggerEnter两个函数在日常的开发中很常见但也容易混淆,下面说一说两者的区别。 碰撞器(Collider)与触发器(Trigger)的概念 碰撞器(Collider)和触发器ÿ…...
2023年12月【考试战报】|ORACLE OCP 19C考试通过
2023年10月【考试战报】|ORACLE OCP 19C考试通过-CSDN博客文章浏览阅读122次。自OCP认证进入中国以来,越来越被大多数DBA所认可,也越来越被企业所重视,90%以上DBA深造,都会选择OCP认证。随着OCP认证在全国范围内的普及,…...
鸿蒙操作系统:从手机到物联网,打造全场景智能体验
随着科技的不断发展,人们对于操作系统的需求也在不断升级。鸿蒙操作系统,作为华为推出的新一代智能终端操作系统,凭借其强大的分布式能力、流畅的用户体验以及丰富的应用生态,正逐渐成为人们关注的焦点。 一、鸿蒙操作系统概述 …...
[Ray Tracing: The Next Week] 笔记
前言 本篇博客参照自《Ray Tracing: The Next Week》教程,地址为:https://raytracing.github.io/books/RayTracingTheNextWeek.html 该教程在ray tracing in one weekend的基础上,增加了运动模糊、BVH树、Texture映射、柏林噪声、光照、体积…...
企业级实战项目:基于 pycaret 自动化预测公司是否破产
本文系数据挖掘实战系列文章,我跟大家分享一个数据挖掘实战,与以往的数据实战不同的是,用自动机器学习方法完成模型构建与调优部分工作,深入理解由此带来的便利与效果。 1. Introduction 本文是一篇数据挖掘实战案例,…...
dl转置卷积
转置卷积 转置卷积,顾名思义,通过名字我们应该就能看出来,其作用和卷积相反,它可以使得图像的像素增多 上图的意思是,输入是22的图像,卷积核为22的矩阵,然后变换成3*3的矩阵 代码如下 import…...
详解结构体(包含结构体内存对齐,柔性数组,位段)【尊嘟很详细】
结构体 结构体是一些值的集合,这些值称为成员变量,结构的成员可以是标量、数组、指针,甚至是其他结构体。 成员名可以与程序中其它变量同名,互不干扰。 结构体的定义 (struct结构名{}) struct books {int a;c…...
我的NPI项目之Android系统升级 - 同平台多产品的OTA
因为公司业务中涉及的面比较广泛,虽然都是提供移动终端PDA,但是使用的场景很多时候是不同的。例如,有提供给大型物流仓储的设备,对这样的设备必需具备扫码功能,键盘(戴手套操作),耐用…...
pnpm包管理器
官网 优点 快速 pnpm 比 npm 快了近 2 倍高效 node_modules 中的所有文件均克隆或硬链接自单一存储位置支持单体仓库 pnpm 内置了对单个源码仓库中包含多个软件包的支持权限严格 pnpm 创建的 node_modules 默认并非扁平结构,因此代码无法对任意软件包进行访问 安…...
flutter websocket发送ping包?
背景 服务端要求flutter客户端隔一段时间发送ping包,以此来建立心跳管理长连接。 代码 import package:web_socket_channel/io.dart; IOWebSocketChannel _channel IOWebSocketChannel.connect(Uri.parse(SocketService.url),pingInterval: const Duration(seco…...
基于采样的自动驾驶规划算法 - PRM,RRT,RRT*,CL-RRT
本文将讲解PRM,RRT,RRT*自动驾驶规划算法原理,不正之处望读者指正 0 前言 机器人运动规划的基本任务:从开始位置到目标位置的运动 (1)如何躲避构型空间出现的障碍物 (2)如何满足机器…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
