Promise学习笔记

一、异步任务的处理

这里我从一个实际的例子来作为切入点:

  • 我们调用一个函数,这个函数中发送网络请求(我们可以用定时器来模拟);
  • 如果发送网络请求成功了,那么告知调用者发送成功,并且将相关数据返回过去;
  • 如果发送网络请求失败了,那么告知调用者发送失败,并且告知错误信息;
    在这里插入图片描述

二、什么是Promise呢?

在上面的解决方案中,我们确实可以解决请求函数得到结果之后,获取到对应的回调,但是它存在两个主要的问题:

  • 第一,我们需要自己来设计回调函数、回调函数的名称、回调函数的使用等;
  • 第二,对于不同的人、不同的框架设计出来的方案是不同的,那么我们必须耐心去看别人的源码或者文档,以便可以理解它这个函数到底怎么用;

我们来看一下Promise的API是怎么样的:

  • Promise是一个类,可以翻译成 承诺、许诺 、期约;
  • 当我们需要给予调用者一个承诺:待会儿我会给你回调数据时,就可以创建一个Promise的对象;
  • 在通过new创建Promise对象时,我们需要传入一个回调函数,我们称之为executor
    这个回调函数会被立即执行,并且给传入另外两个回调函数resolve、reject;
    当我们调用resolve回调函数时,会执行Promise对象的then方法传入的回调函数
    当我们调用reject回调函数时,会执行Promise对象的catch方法传入的回调函数

三、Promise的代码结构

在这里插入图片描述

上面Promise使用过程,我们可以将它划分成三个状态:

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝;
    当执行executor中的代码时,处于该状态;
  • 已兑现(fulfilled): 意味着操作成功完成;
    执行了resolve时,处于该状态;
  • 已拒绝(rejected): 意味着操作失败;
    执行了reject时,处于该状态;

四、Promise重构请求

那么有了Promise,我们就可以将之前的代码进行重构了:
在这里插入图片描述
在这里插入图片描述

五、Executor

Executor是在创建Promise时需要传入的一个回调函数,这个回调函数会被立即执行,并且传入两个参数:
在这里插入图片描述
通常我们会在Executor中确定我们的Promise状态:

  • 通过resolve,可以兑现(fulfilled)Promise的状态,我们也可以称之为已决议(resolved);
  • 通过reject,可以拒绝(reject)Promise的状态;

这里需要注意:一旦状态被确定下来,Promise的状态会被 锁死,该Promise的状态是不可更改的

  • 在我们调用resolve的时候,如果resolve传入的值本身不是一个Promise,那么会将该Promise的状态变成兑现(fulfilled);
  • 在之后我们去调用reject时,已经不会有任何的响应了:
  • 在这里插入图片描述

六、resolve不同值的区别

  • 情况一:如果resolve传入一个普通的值或者对象,那么这个值会作为then回调的参数;
    在这里插入图片描述

  • 情况二:如果resolve中传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态:
    在这里插入图片描述

  • 情况三:如果resolve中传入的是一个对象,并且这个对象有实现then方法,那么会执行该then方法,并且根据then方法的结果来决定Promise的状态:
    在这里插入图片描述

七、Promise的实例方法——then方法

7.1 一个Promise的then方法是可以被多次调用的:

  • 每次调用我们都可以传入对应的fulfilled(成功的)回调;
  • 当Promise的状态变成fulfilled的时候,这些(成功的)回调函数都会被执行;
    在这里插入图片描述

7.2 then方法可以接受两个参数

then方法是Promise对象上的一个方法:它其实是放在Promise的原型上的 Promise.prototype.then

then方法接受两个参数:

  • fulfilled的回调函数:当状态变成fulfilled时会回调的函数;
  • reject的回调函数:当状态变成reject时会回调的函数;

在这里插入图片描述

7.3 then方法的返回值

then方法本身是有返回值的,它的返回值是一个Promise,所以我们可以进行如下的链式调用:

  • 但是then方法返回的Promise到底处于什么样的状态呢? Promise有三种状态,那么这个Promise处于什么状态呢?
  • 当then方法中的回调函数本身在执行的时候,那么它处于pending状态;
  • 当then方法中的回调函数返回一个结果时,那么它处于fulfilled状态,并且会将结果作为resolve的参数;
    情况一:返回一个普通的值; 在这里插入图片描述
    情况二:返回一个Promise;
    在这里插入图片描述

情况三:返回一个thenable值;
在这里插入图片描述

  • 当then方法抛出一个异常时,那么它处于reject状态;
    在这里插入图片描述
    在这里插入图片描述

九、Promise的实例方法——catch方法

9.1 catch方法可以多次调用

catch方法也是Promise对象上的一个方法:它也是放在Promise的原型上的 Promise.prototype.catch

一个Promise的catch方法是可以被多次调用的:

  • 每次调用我们都可以传入对应的reject回调;
  • 当Promise的状态变成reject的时候,这些回调函数都会被执行;
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9.2 catch方法的返回值

事实上catch方法也是会返回一个Promise对象的,所以catch方法后面我们可以继续调用then方法或者catch方法:

下面的代码,后续是catch中的err result打印,还是then中的res result打印呢?
在这里插入图片描述
在这里插入图片描述

答案:res result打印,这是因为catch传入的回调在执行完后,默认状态依然会是fulfilled的,因为是fulfilled状态,所以会执行then里面的回调函数;

如果我们希望后续继续执行catch,那么需要抛出一个异常:
在这里插入图片描述

十、Promise的实例方法——finally方法

finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象无论变成fulfilled还是reject状态,最终都会被执行的代码
finally方法是不接收参数的,因为无论前面是fulfilled状态,还是reject状态,它都会执行。

在这里插入图片描述
在这里插入图片描述

十一、Promise的类方法——resolve方法

前面我们学习的then、catch、finally方法都属于Promise的实例方法,都是存放在Promise的prototype上的。
下面我们再来学习一下Promise的类方法:

有时候我们已经有一个现成的内容了,希望将其转成Promise来使用,这个时候我们可以使用 Promise.resolve 方法来完成。

  • Promise.resolve的用法相当于new Promise,并且执行resolve操作:
    在这里插入图片描述
    在这里插入图片描述

resolve参数的形态:

  • 情况一:参数是一个普通的值或者对象
    在这里插入图片描述

  • 情况二:参数本身是Promise
    在这里插入图片描述

  • 情况三:参数是一个thenable
    在这里插入图片描述

十二、Promise的类方法——reject方法

reject方法类似于resolve方法,只是会将Promise对象的状态设置为reject状态。
Promise.reject的用法相当于new Promise,只是会调用reject:
在这里插入图片描述
注意:Promise.reject传入的参数无论是什么形态,都会直接作为reject状态的参数传递到catch的
在这里插入图片描述

十三、Promise的类方法——all方法

另外一个类方法是Promise.all:

  • 它的作用是将多个Promise包裹在一起形成一个新的Promise;
  • 新的Promise状态由包裹的所有Promise共同决定:
    所有的Promise状态变成fulfilled状态时,新的Promise状态为fulfilled,并且会将所有Promise的返回值 组成一个数组; 当有一个Promise状态为reject时,新的Promise状态为reject,并且会将第一个reject的返回值作为参数
    在这里插入图片描述
    在这里插入图片描述
    all方法有一个缺陷:
    当有其中一个Promise变成reject状态时,新Promise就会立即变成对应的reject状态。 那么对于resolved的,以及依然处于pending状态的Promise,我们是获取不到对应的结果的;

十四、Promise的类方法——allSettled方法

在ES11(ES2020)中,添加了新的API Promise.allSettled:

  • 该方法会在所有的Promise都有结果(settled),无论是fulfilled,还是reject时,才会有最终的状态;
  • 并且这个Promise的结果一定是fulfilled的
    在这里插入图片描述
    我们来看一下打印的结果:
  • allSettled的结果是一个数组,数组中存放着每一个Promise的结果,并且是对应一个对象的;
  • 这个对象中包含status状态,以及对应的value值;

十五、Promise的类方法——race方法

如果有一个Promise有了结果,我们就希望决定最终新Promise的状态,那么可以使用race方法:

  • race是竞技、竞赛的意思,表示多个Promise相互竞争,谁先有结果,那么就使用谁的结果
    在这里插入图片描述
    在这里插入图片描述

十六、Promise的类方法——any方法

any方法是ES12中新增的方法,和race方法是类似的:

  • any方法会等到一个fulfilled状态,才会决定新Promise的状态;
  • 如果所有的Promise都是reject的,那么也会等到所有的Promise都变成rejected状态;
    在这里插入图片描述

如果所有的Promise都是reject的,那么会报一个AggregateError的错误:
在这里插入图片描述
在这里插入图片描述

总结:

  1. Promise.all([ ]): 等到所有的Promise状态变成fulfilled,最终结果才是fulfilled。只要有一个是rejected,就返回这个rejected的Promise的执行结果。
  2. Promise.allSettled([ ]): 等所有Promise都有结果才返回,并且这个Promise的结果一定是fulfilled的,返回的结果放在一个数组中,数组中保存着每个Promise的执行结果。
  3. Promise.race([ ]):多个Promise相互竞争,谁先有结果,那么就使用谁的结果
  4. Promise.any([ ]):等到一个fulfilled(成功的)Promise,谁先成功,那么就使用谁的结果;都不成功,返回所有的Promise的reject结果,放在一个数组里。

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

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

相关文章

JS高级——Iterator迭代器、Generator生成器

一、什么是迭代器? 在JavaScript中,迭代器也是一个具体的对象,这个对象需要符合迭代器协议(iterator protocol): 迭代器协议定义了产生一系列值(无论是有限还是无限个)的标准方式&…

删除一行下方单元格上移_快速删除Excel工作表多余空单元格

从其他地方复制了数据,有时候会出现多余的空单元格。手动删除很麻烦,就像下面的图中的工作表区域。下面介绍一种方法,可以快速删除多余空单元格。1.选中目标区域,在这里就选中A1:A9的单元格区域。2.按键盘上的F5或者CtrlG。3.点击…

JS高级——await-async

一、异步函数 async function async关键字用于声明一个异步函数: async是asynchronous单词的缩写,异步、非同步;sync是synchronous单词的缩写,同步、同时; async异步函数可以有很多中写法: 二、异步函…

图象关于y轴对称是什么意思_数学概念丨“图象”与“图像”是有区别的 ,你知道吗?...

你与数学间只差一个公众号解读教材教法,研究解题策略,传播数学文化,推广数学应用,推送知识干货,分享学习方法。精彩分享初一数学全国各地期中试卷150套,word版初二数学全国各地期中试卷150套,wo…

数据压缩 第二次作业

1.设X是一个随机变量&#xff0c;取值范围是一个包含M个字母的符号集。证明0<H(X)<log2M。 2.证明如果观察到一个序列的元素为iid分布&#xff0c;则该序列的熵等于一阶熵。 3.给定符号集A{a1,a2,a3,a4},求以下条件下的一阶熵&#xff1a; (a) p(a1)p(a2)p(a3)p(a4)1/4 (…

JS高级——错误处理

一、错误处理方案 开发中我们会封装一些工具函数&#xff0c;封装之后给别人使用&#xff1a; 在其他人使用的过程中&#xff0c;可能会传递一些参数&#xff1b;对于函数来说&#xff0c;需要对这些参数进行验证&#xff0c;否则可能得到的是我们不想要的结果&#xff1b; …

k1658停运到什么时候_春节网购别被商家忽悠!春节快递不停运,但价格会和平时不一样...

现在临春节已经越来越近了&#xff0c;这些天也是网购订单大幅度增长的时间&#xff0c;因为年底的时候很多人的网购需求都爆发了&#xff0c;会想着买各种东西到家&#xff0c;包括年货的置办。也就是在这种时候&#xff0c;很多网店过年的时候都会休息&#xff0c;但是也有一…

JS高级——模块化学习笔记

一、什么是模块化&#xff1f; 到底什么是模块化、模块化开发呢&#xff1f; 事实上模块化开发最终的目的是将程序划分成一个个小的结构&#xff1b;这个结构中编写属于自己的逻辑代码&#xff0c;有自己的作用域&#xff0c;不会影响到其他的结构&#xff1b;这个结构可以将…

JS高级——JSON、数据存储学习笔记

在目前的开发中&#xff0c;JSON是一种非常重要的数据格式&#xff0c;它并不是编程语言&#xff0c;而是一种可以在服务器和客户端之间传输的数据格式。 JSON的全称是JavaScript Object Notation&#xff08;JavaScript对象符号&#xff09;&#xff1a; JSON是由Douglas Cro…

beautifulsoup获取属性_Python爬虫常用模块:BeautifulSoup

BeautifulSoup用途 BeautifulSoup 借助网页的结构和属性等特性来解析网页&#xff0c;可以用它来方便地从网页中提取所需信息。 BeautifulSoup自动将输入文档转换为Unicode编码&#xff0c;输出文档转换为UTF-8编码。BeautifulSoup依赖于解析器 它除了支持Python标准库中的HTML…

CSS3选择器的研究

属性选择器 [title]:选择带有title属性的元素 [titlehello]:选择属性是title并且值是hello的元素 [title~hello]:选择属性是title并且部分值是hello的元素&#xff0c;hello需要是单独的值&#xff0c;以空格分开 [title*hello]:选择属性是title并且其中包含了hello的元素 [tit…

手写实现简单的Vue事件总线

一、什么是事件总线 自定义事件总线属于一种观察者模式&#xff0c;其中包括三个角色&#xff1a; 发布者&#xff08;Publisher&#xff09;&#xff1a;发出事件&#xff08;Event&#xff09;&#xff1b;订阅者&#xff08;Subscriber&#xff09;&#xff1a;订阅事件&a…

手写实现深拷贝函数

对象相互赋值的一些关系&#xff0c;分别包括&#xff1a; 引入的赋值&#xff1a;指向同一个对象&#xff0c;相互之间会影响&#xff1b;对象的浅拷贝&#xff1a;只是浅层的拷贝&#xff0c;内部引入对象时&#xff0c;依然会相互影响&#xff1b;对象的深拷贝&#xff1a;两…

第一款支持容器和云部署的开源数据库Neo4j 3.0

导读Neo4j 3.0.0 正式发布&#xff0c;这是 Neo4j 3.0 系列的第一个版本。此版本对内部架构进行了全新的设计&#xff1b;提供给开发者更强大的生产力&#xff1b;提供更广阔的部署选择。Neo4j 3.0 被认为是世界上最具伸缩性的基于Java的图片数据库。Neo4j 3.0.0 主要的新特性&…

手写防抖和节流函数

一、认识防抖debounce函数 我们用一副图来理解一下它的过程&#xff1a; 当事件触发时&#xff0c;相应的函数并不会立即触发&#xff0c;而是会等待一定的时间&#xff1b;当事件密集触发时&#xff0c;函数的触发会被频繁的推迟&#xff1b;只有等待了一段时间也没有事件触…

中webgl解析json_WebGL蒙皮(下)

今天继续学习webgl一个重要功能&#xff1a;skinning(蒙皮)&#xff0c;内容来自学习网站webglfundamentals&#xff0c;这里仅供学习交流&#xff0c;原文链接&#xff1a;https://webglfundamentals.org/webgl/lessons/zh_cn/webgl-skinning.html。文章并非原创&#xff01;如…

Vue权限控制——动态注册路由

需求&#xff1a;实现后台管理系统不同用户的权限控制 根据登录的用户的角色动态展示后台管理系统的左侧菜单栏的菜单列表内容&#xff0c;然后还要动态注册对应子菜单的路由 菜单列表内容应该通过后端接口返回&#xff1a; sort为1表示当前项有子菜单sort为2表示当前项没有子…

react不同环境不同配置angular_前端问题集:vue配置环境-给不同的环境配不同的打包命令...

通过vue-cli脚手架构建出一个前端项目&#xff0c;通过npm run build打包&#xff0c;发布到线上&#xff0c;但是这样做需要每次都手动修改接口地址。我们可以通过自行配置打包命令实现无需修改接口地址&#xff0c;打各个环境的包。文档结构大致如下图&#xff1a;1.找到conf…

基于Element-plus封装配置化表单组件(组件的v-model实现)

一、预备知识 1.1 组件的v-model 前面我们在input中可以使用v-model来完成双向绑定&#xff1a; 这个时候往往会非常方便&#xff0c;因为v-model默认帮助我们完成了两件事&#xff1b;v-bind:value的数据绑定 和 input的事件监听&#xff1b; 如果我们现在封装了一个组件…

Scala IDE for Eclipse的下载、安装和WordCount的初步使用(本地模式和集群模式)

不多说&#xff0c;直接上干货&#xff01; 这篇博客是&#xff0c; 是在Scala IDEA for Eclipse里maven创建scala和java代码编写环境。 Scala IDEA for Eclipse里用maven来创建scala和java项目代码环境&#xff08;图文详解&#xff09; 本博文包括&#xff1a; Scala IDE fo…