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)如何满足机器…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...