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) })
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/763799.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CrossOver 23 用户可以免费升级到 CrossOver24吗?CrossOver用户如何升级呢?

也就是上个月(2024年2月底)左右,CrossOver 刚刚更新了 24 版本,CrossOver更新的内容有哪些,大家可以参考这篇文章:CrossOver24.0新功能介绍,这篇文章详细介绍了CrossOver24有哪些新特点&#xf…

Echarts中手柄样式更改

代码: dataZoom: [{start: 0,end: 100,left: 100,bottom: 0,right: 140,backgroundColor: yellow,borderRadius: 15,borderColor: green,dataBackground: {lineStyle: {width: 0},areaStyle: {color: black,opacity: 1,}},selectedDataBackground: {lineStyle: {wi…

MySQL数据库操作学习(6)事务与pymysql

文章目录 1、视图2、索引3、存储引擎4、事务(重点)①介绍②事务隔离级别 5、pymysql(重点)①导入模块②链接数据库对象③隐式事务④显性事务 1、视图 视图(View)是一种虚拟的表,它是基于一个或多个实际表(或其他视图)…

搭建自己的博客-拾壹博客

写在前面 唠叨两句 作为一个技术开发人员,没有一个自己的博客,人生注定缺少点什么东西,是不是?最近研究了一些博客搭建,本文是使用开源项目”拾壹博客“进行搭建。 推荐等级 所需技术难度:4星 后续自定义…

数据类型转换篇(二)

文章目录 7.11 float()7.12 hex()7.13 int()7.14 list()7.15 oct()7.16 ord()7.17 repr()7.18 set()7.19 str()7.20 tuple() 7.11 float() float() 是 Python 的内置函数,用于将一个数值或数值表示的字符串转换成浮点数(floating point number&#xff…

全栈的自我修养 ———— uniapp中加密方法

直接按部就班一步一步来 一、首先创建一个js文件填入AES二、创建加密解密方法三、测试 一、首先创建一个js文件填入AES 直接复制以下内容 /* CryptoJS v3.1.2 code.google.com/p/crypto-js (c) 2009-2013 by Jeff Mott. All rights reserved. code.google.com/p/crypto-js/wi…

Matlab快捷键与函数

注释:注释对于代码的重要性我们就不做过多的解释了。不做注释的代码不是好代码。选中要注释的语句,按快捷键CtrlR,或者在命令行窗口上面的注释地方可以进行注释。当然也可以直接在语句前面“%”就可以(注意:一定要用英文符号&…

ES查询小技能

文章目录 引言I Kibana 查询命令1.1 分页查询1.2 索引总数1.3 多个查询条件1.5 查询结果去重II 查询文档2.1 查询类型2.2 结果解析2.3 分页和距离排序2.4 高亮III 创建索引并添加映射IV 集群状态4.1 查询集群状态4.2 查看索引数据V 设置账号密码<

移动硬盘故障解析:解决无法访问且位置不可用问题

在我们日常的工作和生活中&#xff0c;移动硬盘已成为存储和传输数据的重要工具。然而&#xff0c;有时我们会遇到移动硬盘无法访问且位置不可用的情况&#xff0c;这无疑给数据的存储和访问带来了极大的困扰。本文将深入探讨这一问题&#xff0c;分析其原因&#xff0c;并给出…

如何做时间管理?

前言 本篇是最近学习工作提效系列课程的第一篇&#xff0c;如何做时间管理&#xff1f;关于时间管理的内容老生常谈了&#xff0c;我自己之前也分享过针对时间管理的一些思考&#xff0c;比如 近期对「时间管理」的一些思考&#xff0c; 还有高效能人士的七个习惯的分享【读书…

计算地球圆盘负荷产生的位移

1.研究背景 计算受表面载荷影响的弹性体变形问题有着悠久的历史&#xff0c;涉及到许多著名的数学家和物理学家&#xff08;Boussinesq 1885&#xff1b;Lamb 1901&#xff1b;Love 1911&#xff0c;1929&#xff1b;Shida 1912&#xff1b;Terazawa 1916&#xff1b;Munk &…

Springboot笔记-02

1.使用Spring Initializer快速创建Spring Boot项目 IDE都支持使用Spring的项目创建向导快速创建一个Spring Boot项目&#xff1b; 选择我们需要的模块&#xff1b; 向导会联网创建Spring Boot项目&#xff1b; 默认生成的Spring Boot项目&#xff1b; 主程序已经生成好了&#…

Linux:http协议初步认识

文章目录 OSI七层模型http协议域名路径信息请求和响应 编写一个httpserver OSI七层模型 在结束了前面对于序列化反序列化等内容的学习后&#xff0c;重新回到对于OSI模型的部分 如上所示的是对于OSI接口的示意图&#xff0c;在这当中可以看到会话层的概念&#xff0c;会话层的…

QPainter绘图和QChart图表和QCustomplot绘曲线图

一&#xff0c;QPainter绘图 Qt里的所有绘图&#xff0c;比如一个按钮和一个Label的显示&#xff0c;都有绘图系统来执行。绘图系统基于 QPainter、QPaintDevice和QPainEngine类。QPainter是可以直接用来操作绘图的类&#xff0c;而 QPaintDevice和QPainEngine都比QPainter更底…

FinalShell下载安装 + FinallShell远程连接Linux 教程

图形化&#xff0c;命令行 : windows下的图形化和命令行 : Linux下的图形化和命令行 : 在Linux下&#xff0c;普遍使用命令行操作 ; FinalShell 下载安装: 下载安装地址 : 这里给出windows的下载地址 : install 双击打开就好 : 然后点击下一步 : 选择下载地址&…

vue学习日记14:工程化开发脚手架Vue CLI

一、概念 二、安装 1.全局安装&查看版本 注意启动cmd输入命令 要以管理员运行哦 安装了一次就行以后不用再创建了 yarn global addvue/cli vue --version 显示了版本号即可 2.创建项目架子 创建项目的路径在哪 项目就在哪 项目名字不能用中文 vue create project-n…

搜索测试题题解(3月19号总结)

目录 1.Dungeon Master 2.Oil Deposits 3.Find a way 1.Dungeon Master Sample InputcopyOutputcopy 3 4 5 S.... .###. .##.. ###.###### ##### ##.## ##...##### ##### #.### ####E1 3 3 S## #E# ###0 0 0Escaped in 11 minute(s). Trapped! 这道题与普通的bfs模板题就是…

线性顺序表算法库

list.cpp 具体函数实现 #include <stdio.h> #include "list.h" #include <malloc.h>/************************************************** ①函数名: CreateList 功 能: 用数组构建顺序表 参 数: ①SqList *&L:传入的线性表 ②ElemType a[]:使用…

Iterator对象功能学习

package config;import java.util.Iterator; import java.util.Properties; import java.util.Set;/*** 这个类演示了如何使用Properties类来存储和访问键值对。* Properties类继承自Hashtable&#xff0c;因此它可以用来存储键值对数据&#xff0c;且支持同步。*/ public clas…

代码随想录算法训练营第十七天|110、平衡二叉树

110. 平衡二叉树 已解答 简单 相关标签 相关企业 给定一个二叉树&#xff0c;判断它是否是 平衡二叉树 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,3,3,null,null,4,4] 输出&am…