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

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结尾的递增三元组,也就是未来的决策受过去影响,专业的说就是有后效性。需要强化约束条件&#xff0…...

蓝桥杯每日一题——棋盘

问题描述 小蓝拥有 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模式开发),系统具有完整的源代码和数据库&#xff…...

Java反射机制的讲解及其示例说明

Java 反射机制是指在运行时动态地获取类的信息以及操作对象的方式。它允许程序在运行时检查和操作类、方法、属性等,而不需要在编译时就确定这些属性。通过反射机制,我们可以在运行时动态地创建对象、调用方法、获取属性等。 Java 反射机制提供了以下主…...

20240309web前端_第二周作业_完成游戏导航栏

作业&#xff1a;游戏导航栏 成果展示&#xff1a; 完整代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0…...

五、大模型-Prompt

一、prompt是什么 在大型语言模型集成中&#xff0c;"prompt" 是指您向模型提供的输入文本或指令&#xff0c;以引导模型生成特定类型的响应。这个 prompt 可以是一个问题、一段描述、一个任务说明&#xff0c;甚至是一部分对话历史记录等。通过设计和优化 prompt&a…...

【网络安全】 MSF提权

本文章仅用于信息安全学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若读者因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与作者无关。 环境准备&#xff1a; 名称系统位数IP攻击机Kali Linux6410.3.0.231客户端Windows 76410.3.0.234…...

STM32CubeMX RTC万年历功能缺失的F103日期保存方案优化

1. STM32F103 RTC日期丢失问题解析 第一次用STM32F103做带RTC功能的产品时&#xff0c;我就被这个坑绊倒了。明明接了纽扣电池&#xff0c;断电后时间能正常走&#xff0c;但日期总会莫名其妙重置到初始值。后来查资料才发现&#xff0c;这是STM32CubeMX生成代码时的"祖传…...

龙虾白嫖指南,请查收~诠

1. 什么是 Apache SeaTunnel&#xff1f; Apache SeaTunnel 是一个非常易于使用、高性能、支持实时流式和离线批处理的海量数据集成平台。它的目标是解决常见的数据集成问题&#xff0c;如数据源多样性、同步场景复杂性以及资源消耗高的问题。 核心特性 丰富的数据源支持&am…...

磁敏式传感器实战解析:从霍尔效应到工业测速应用

1. 磁敏式传感器入门&#xff1a;从霍尔效应说起 第一次接触磁敏式传感器是在五年前的一个工业自动化项目上&#xff0c;当时需要精确测量电机转速&#xff0c;传统的光电编码器在油污环境下频频失效。机械组的老师傅从工具箱里掏出个火柴盒大小的黑色元件说&#xff1a;"…...

第16讲:C语⾔内存函数

目录 memcpy使⽤memmove使⽤memset函数的使⽤memcmp函数的使⽤1.memcpy&#xff08;1&#xff09;功能&#xff1a; memcpy 是完成内存块拷⻉的&#xff0c;不关注内存中存放的数据是啥。函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到 destination 指向的内存位…...

Yosys内部数据结构与优化流程深度解析

1. Yosys工具与RTLIL数据结构概述 Yosys作为开源硬件综合工具链的核心组件&#xff0c;其内部实现了一套名为RTLIL&#xff08;Register Transfer Level Intermediate Language&#xff09;的中间表示语言。这套数据结构的设计直接决定了工具的性能上限和优化潜力。我第一次接触…...

FigmaCN中文插件:3分钟快速安装,彻底告别英文界面困扰

FigmaCN中文插件&#xff1a;3分钟快速安装&#xff0c;彻底告别英文界面困扰 【免费下载链接】figmaCN 中文 Figma 插件&#xff0c;设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma复杂的英文界面而烦恼吗&#xff1f;每次设计都…...

算力云实战:用阿里云盘+JupyterLab搞定大模型数据集上传,附完整VSCode远程Python环境配置

算力云实战&#xff1a;阿里云盘与JupyterLab高效传输大模型数据集全指南 当你在本地工作站完成了一个15GB的BERT预训练数据集整理&#xff0c;正准备上传到云端GPU实例进行微调时&#xff0c;传统SFTP传输进度条却卡在23%整整两小时不动——这种场景对AI开发者来说再熟悉不过。…...

13.将手写 Agent 主流程迁移为 LangGraph 最小闭环,并接回 FastAPI + session 外壳

目 录前 言开始动手项目结构重构数据State化函数Node化串起Node形成Graph收尾前 言 咱们前面的代码是通过手写Agent工作流程&#xff0c;实现了一个论文RAG问答系统&#xff0c;但是在实际生产环境中不会用这种纯手写工作逻辑项目&#xff0c;更多的是使用现有框架比如LangGra…...

RS485 RE、DE

在RS485通信中&#xff0c;RE 和 DE 是两个关键的控制引脚&#xff0c;用于管理收发器的数据流向&#xff0c;是实现半双工通信的核心。 引脚定义与功能引脚名称全称功能描述典型电平逻辑REReceive Enable&#xff08;接收使能&#xff09;控制接收器的使能与否。低电平有效&am…...

Freertos堆管理算法解析:如何为STM32选择最优内存方案

FreeRTOS堆管理算法深度解析&#xff1a;STM32工业控制项目中的内存优化实践 在工业控制领域&#xff0c;实时性和可靠性是系统设计的核心诉求。STM32系列微控制器凭借其优异的性能价格比&#xff0c;成为众多工业设备的首选平台。而FreeRTOS作为一款轻量级实时操作系统&#x…...