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

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)和触发器&#xff…...

2023年12月【考试战报】|ORACLE OCP 19C考试通过

2023年10月【考试战报】|ORACLE OCP 19C考试通过-CSDN博客文章浏览阅读122次。自OCP认证进入中国以来,越来越被大多数DBA所认可,也越来越被企业所重视,90%以上DBA深造,都会选择OCP认证。随着OCP认证在全国范围内的普及&#xff0c…...

鸿蒙操作系统:从手机到物联网,打造全场景智能体验

随着科技的不断发展,人们对于操作系统的需求也在不断升级。鸿蒙操作系统,作为华为推出的新一代智能终端操作系统,凭借其强大的分布式能力、流畅的用户体验以及丰富的应用生态,正逐渐成为人们关注的焦点。 一、鸿蒙操作系统概述 …...

[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)如何满足机器…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

PHP和Node.js哪个更爽?

先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

线程同步:确保多线程程序的安全与高效!

全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中&#xff0…...