JavaScript高级(十四)----prmise
异步请求的处理方式
回调函数
所谓的回调函数就是函数作为参数的传递,在一个函数内部调用另一个函数,调用的同时可以把内部函数的数据传递出来,他的使用场景就是异步操作,数据需要等待一段时间才能返回的情况下可以使用回调函数
function foo(url, successCallback, failtureCallback) {// 假设这是网络请求,需要请求完毕才能返回给用户使用setTimeout(() => {if (url === 'success') {// 假设successCallback callback === 'function'successCallback && successCallback({ code: '200', message: '请求成功' })} else {//failtureCallback callback === 'function'failtureCallback && failtureCallback({ code: '-200', message: '请求失败' })}}, 2000)}foo('failture',res => console.log(res),err => console.log(err))
回调函数处理异步的弊端
- 如果是我们自己封装的函数,那么我们在封装的时候必须要自己设计好callback名称, 并且使用好,否则容易造成不理解。
- 如果我们使用的是别人封装的函数或者一些第三方库, 那么我们必须去看别人的源码或者文档, 才知道它这个函数需要怎么去获取到结果。
- 异步嵌套太多,容易造成回调地狱,代码看起来很不容易理解,可维护可阅读性都不高,找bug要花很多时间。
-
function foo(url, successCallback, failtureCallback) {// 假设这是网络请求,需要请求完毕才能返回给用户使用setTimeout(() => {if (url === 'success') {successCallback && successCallback({ code: '200', message: '请求成功' })} else {failtureCallback && failtureCallback({ code: '-200', message: '请求失败' })}}, 1000)}foo('success',// 成功回调(res) => {console.log(`第一次数据请求成功,接着请求第二次数据${res.code}`)foo('success', (res) => {console.log(`第二次数据请求成功,接着请求第三次数据${res.code}`)foo('success', (res) => {console.log(`第三次数据请求成功,接着请求第四次数据${res.code}`)foo('success', (res) => {console.log(`第四次数据请求成功,接着请求第五次数据${res.code}`)foo('success', (res) => {console.log(`第五次数据请求成功,接着请求第六次数据${res.code}`)foo('failture', (res) => {console.log(`第六次数据请求成功,接着请求第七次数据${res.code}`)}, (err) => { console.log(`第六次数据请求失败,gg了${err.code}`) })}, (err) => { console.log(err) })}, (err) => { console.log(err) })}, (err) => { console.log(err) })}, (err) => { console.log(err) })},// 失败回调(err) => { console.log(err) })上面代码就是典型的回调地狱,试问,如果你在真实项目开发中遇见这样的代码,你能够分析出问题的所在吗?所以这不是一种合理解决异步的方案。
Promise
Promise是一个类,实现异步编程的方法。
Promise的状态一旦被确定下来,无法被更改,resolve、reject两个函数不会代码禁止向下执行,为了防止继续向下执行,要加上return。
Promise的三个状态
- 待定( pending ) : 初始状态,既没有被兑现,也没有被拒
- 已兑现( fulfilled ) : 意味着操作已经完成 resolve
- 已拒绝 (rejected):意味着操作失败 reject
resolve不同值的区别
- 如果resolve传入一个普通的值或者对象,那么这个值会作为then回调的参数
const promise = new Promise((resolve, reject) => { resolve("普通值") });promise.then(res => {console.log(res)}, err => { })
- 如果resolve中传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态
const promise = new Promise((resolve, reject) => {resolve(new Promise((resolve, reject) => {reject("我是新的promies, 我要改变之前promise的状态,这里会执行err")}))});promise.then(res => {console.log(res)}, err => {console.log(err)})
- 如果resolve中传入的是一个对象,并且这个对象有实现then方法,那么会执行该then方法,并且根据 then方法的结果来决定Promise的状态
const promise = new Promise((resolve, reject) => {const obj = {name: 'obj',then(resolve, reject) {reject('传入一个对象,对象里面有then方法,会改变之前promise的状态')}}resolve(obj)});promise.then(res => {console.log(res)}, err => {console.log(err)})then 方法的参数
// then方法接受两个参数new Promise((resolve, reject) => {reject('嘿嘿')}).then(res => {console.log('resolve触发的回调函数');},err => {console.log('reject触发的回调函数');})// 等价于new Promise((resolve, reject) => {reject('嘿嘿')}).then(res => { console.log('resolve触发的回调函数') }).catch(err => { console.log('reject触发的回调函数') })then 方法多次调用
const promise = new Promise((resolve, reject) => {reject('嘿嘿嘿')})promise.then(res => { console.log(res) }).catch(err => { console.log(err) })promise.then(res => { console.log(res) }).catch(err => { console.log(err) })then/catch 方法返回值
then/catch方法本身返回的就是一个Promise,所以我们可以进行链式调用。
-
// catch打印完后又返回了一个promise 所以后面的then又会打印new Promise((resolve, reject) => {reject('嘿嘿')}).then(res => { console.log('resolve触发的回调函数'); }).catch(err => { console.log('reject触发的回调函数'); return 123 }).then(res => { console.log(res) })finally 方法
finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象无论变成fulfilled还是reject状态,最终都会被执行的代码
new Promise((resolve, reject) => {reject('reject')}).then(res => { console.log(res) }).catch(err => { console.log(err) }).finally(() => { console.log('我是最后被执行的') })all 方法
它的作用是将多个Promise包裹在一起形成一个新的Promise。新的Promise状态由包裹的所有Promise共同决定。
// 当所有的Promise状态变成fulfilled状态时,新的Promise状态为fulfilled,并且会将所有Promise的返回值 组成一个数组; const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('1')}, 1000)})const p2 = new Promise((resolve, reject) => {setTimeout(() => {resolve('2')}, 2000)})const p3 = new Promise((resolve, reject) => {setTimeout(() => {resolve('3')}, 3000)})Promise.all([p3, p2, p1]).then(res => {console.log(res)}).catch(err => {console.log(err)})//当有一个Promise状态为reject时,新的Promise状态为reject,并且会将第一个reject的返回值作为参数;const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('1')}, 1000)})const p2 = new Promise((resolve, reject) => {setTimeout(() => {reject('2')}, 2000)})const p3 = new Promise((resolve, reject) => {setTimeout(() => {reject('3')}, 3000)})Promise.all([p3, p2, p1]).then(res => {console.log(res)}).catch(err => {console.log(err)})allSettled 方法
all方法有一个缺陷:当有其中一个Promise变成reject状态时,新Promise就会立即变成对应的reject状态。
该方法会在所有的Promise都有结果(settled),无论是fulfilled,还是reject时,才会有最终的状态。
const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve(11111)}, 1000);})const p2 = new Promise((resolve, reject) => {setTimeout(() => {reject(22222)}, 2000);})const p3 = new Promise((resolve, reject) => {setTimeout(() => {resolve(33333)}, 3000);})// allSettledPromise.allSettled([p1, p2, p3]).then(res => {console.log(res)}).catch(err => {console.log(err)race 方法
如果有一个Promise有了结果,我们就希望决定最终新Promise的状态,那么可以使用race方法。
const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('1')}, 1000)})const p2 = new Promise((resolve, reject) => {setTimeout(() => {reject('2')}, 998)})const p3 = new Promise((resolve, reject) => {setTimeout(() => {resolve('3')}, 1002)})// 不管是resolve 还是reject 谁先有结果,那么就使用谁的结果Promise.race([p1, p2, p3]).then(res => { console.log(res) }).catch(err => { console.log(err) })any 方法
和race方法是类似的,any方法会等到一个fulfilled状态,才会决定新Promise的状态,如果所有的Promise都是reject的,那么会报一个AggregateError的错误。
const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('1')}, 1000)})const p2 = new Promise((resolve, reject) => {setTimeout(() => {reject('2')}, 998)})const p3 = new Promise((resolve, reject) => {setTimeout(() => {resolve('3')}, 1002)})// 会打印p1 Promise.any([p1, p2, p3]).then(res => { console.log(res) }).catch(err => { console.log(err) })
相关文章:
JavaScript高级(十四)----prmise
异步请求的处理方式 回调函数 所谓的回调函数就是函数作为参数的传递,在一个函数内部调用另一个函数,调用的同时可以把内部函数的数据传递出来,他的使用场景就是异步操作,数据需要等待一段时间才能返回的情况下可以使用回调函数…...
28 OpenCV 轮廓周围绘制图形
文章目录 approxPolyDP 轮廓周围绘制矩形boundingRectminAreaRect绘制圆和椭圆示例 approxPolyDP 轮廓周围绘制矩形 approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)curve:输入点集,二维点向量的集合appro…...
校企合作,助力人才培养——黄冈师范学院-唯众 “实习实训基地”揭牌仪式顺利举行
3月20日上午,黄冈师范学院计算机学院院长何中林、教务处实习科科长雷汝琳以及计算机学院实验室主任肖飞一行三人,莅临唯众进行参观交流。唯众总经理冉柏权、销售总监舒敏以及董事长助理代西凯进行了热情接待。双方就如何更好地结合企业需求与学院教育资源…...
npm audit fix --force
npm audit fix --force是npm的一个命令,用于自动修复包中的安全漏洞。 其中: - npm audit:审查项目中的依赖包,检查是否存在已知的安全漏洞。 - fix:自动安装相关的补丁来修复发现的漏洞。 - --force:强制安装补丁版本,即使出现不兼容也强制更新。 所以npm audit fix --fo…...
递增四元组
解法: 首先都可以想到dp[i]:第i个元素结尾的递增四元组有dp[i]个 然后发现有一组数据:2,3,6,1,5,8。会出现6结尾和5结尾的递增三元组,也就是未来的决策受过去影响,专业的说就是有后效性。需要强化约束条件࿰…...
蓝桥杯每日一题——棋盘
问题描述 小蓝拥有 n xn 大小的棋盘,一开始棋盘上全都是白子。小蓝进行了 m 次操作,每次操作会将棋盘上某个范围内的所有棋子的颜色取反(也就是白色棋子变为黑色,黑色棋子变为白色)请输出所有操作做完后棋盘上每个棋子的颜色。输入格式 输入的…...
QT6实现创建与操作sqlite数据库及读取实例(一)
一.Qt为SQL数据库提供支持的基本模块(Qt SQL) Qt SQL的API分为不同层: 驱动层 SQL API层 用户接口层 1.驱动层 对于Qt 是基于C来实现的框架,该层主要包括QSqlDriver,QSqlDriverCreator,QSqlDriverCreatorBase,QSqlPlug…...
第十四届蓝桥杯JavaB组省赛真题 - 阶乘求和
/ 10^9考虑前九位,% 10^9保留后9位 解题思路: 求获取结果的后九位数字,需要对10^9取余,因为202320232023这个数字的阶乘太大,必须要减少计算量,因为当一个整数乘以10^9后对其取余,那么结果都为0。 所以我…...
Java毕业设计 基于springboot医院挂号系统 医院管理系统
Java毕业设计 基于springboot医院挂号系统 医院管理系统 springboot医院挂号系统 医院管理系统 功能介绍 用户:登录 首页 个人资料 修改密码 门诊管理 用户挂号 医生:登录 首页 个人资料 修改密码 门诊管理: 用户挂号 处方划价 项目划价 项目缴费 项目…...
【MySQL】基本查询(1)
【MySQL】基本查询(1) 目录 【MySQL】基本查询(1)表的增删改查Create单行数据 全列插入多行数据 指定列插入插入否则更新替换 RetrieveSELECT 列全列查询指定列查询查询字段为表达式为查询结果指定别名结果去重 WHERE 条件英语不…...
一文讲清!进销存管理系统如何实现锁库及库存冻结?计算月加权平均成本?
进销存管理系统中的锁库及库存冻结如何实现?进销存管理系统如何计算月加权平均成本?进销存管理系统又该如何统计和预测采购需求?这些进销存管理难题困扰着许多企业管理者。本文将结合数年从业经验,深入探讨这些进销存管理难题&…...
将本地项目上传至码云
1.打开git,然后进入到项目目录 2.进入到项目目录,然后进行git的初始化 成功后本地项目目录内会多出一个“.git”文件: 指令介绍: git init -- 建立本地仓库 3.在码云上创建仓库,名为“MyMoney” 创建过程参考&…...
虚拟化技术
前言 大家好我是jiantaoyab,这是我所总结作为学习的笔记第十八篇,在这里分享给大家,这篇文章讲虚拟技术就是大家平时用到的云服务器是什么。 虚拟机技术变迁 虚拟机(Virtual Machine)技术,其实就是指在现…...
鸿蒙一次开发,多端部署(一)简介
背景 随着终端设备形态日益多样化,分布式技术逐渐打破单一硬件边界,一个应用或服务,可以在不同的硬件设备之间随意调用、互助共享,让用户享受无缝的全场景体验。而作为应用开发者,广泛的设备类型也能为应用带来广大的…...
数据结构——单向链表(C语言版)
在数据结构和算法中,链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。在C语言中,我们可以使用指针来实现单向链表。下面将详细介绍如何用C语言实现单向链表。 目录 1. 定义节点结构体 2. …...
ideaSSM 工厂效能管理系统bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目
一、源码特点 idea 开发 SSM 工厂效能管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库ÿ…...
Java反射机制的讲解及其示例说明
Java 反射机制是指在运行时动态地获取类的信息以及操作对象的方式。它允许程序在运行时检查和操作类、方法、属性等,而不需要在编译时就确定这些属性。通过反射机制,我们可以在运行时动态地创建对象、调用方法、获取属性等。 Java 反射机制提供了以下主…...
20240309web前端_第二周作业_完成游戏导航栏
作业:游戏导航栏 成果展示: 完整代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0…...
五、大模型-Prompt
一、prompt是什么 在大型语言模型集成中,"prompt" 是指您向模型提供的输入文本或指令,以引导模型生成特定类型的响应。这个 prompt 可以是一个问题、一段描述、一个任务说明,甚至是一部分对话历史记录等。通过设计和优化 prompt&a…...
【网络安全】 MSF提权
本文章仅用于信息安全学习,请遵守相关法律法规,严禁用于非法途径。若读者因此作出任何危害网络安全的行为,后果自负,与作者无关。 环境准备: 名称系统位数IP攻击机Kali Linux6410.3.0.231客户端Windows 76410.3.0.234…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
