尚硅谷Web前端Promise教程从入门到精通——笔记
1. Promise简介
1.1 Promise理解
- 抽象理解:Promise是js中进行异步编程的新解决方案
- 异步编程:自己的理解:需要按照一定顺序进行的编程
- fs,文件操作
- ajax
- 数据库操作
- 定时器
- 之前进行异步编程直接通过回调函数的方式进行,会导致回调地狱
- 回调函数:作为参数的函数
- 回调地狱:回调函数里面嵌套回调函数
- 代码可读性差
- 不便于异常处理
- 异步编程:自己的理解:需要按照一定顺序进行的编程
- 具体理解:
- 从语法上说,Promise是一个构造函数
- 从功能上说,Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值
- 为什么使用Promise
- Promise支持链式调用,可以解决回调地狱问题
- 回调地狱:
- 指定回调函数
- Promise支持链式调用,可以解决回调地狱问题
1.2 Promise初体验
- Promise是一个对象,包含成功、失败等状态,构造函数,then等方法
- Promise构造函数的参数是一个包含异步操作的函数
- 该函数有两个参数,resolve和reject,这两个参数同样也是函数形式
- resolve在函数内的异步操作成功时调用,会将Promise对象状态设置为成功,并且将成功的结果传递给对象,供then的回调函数使用
- reject在函数内的异步操作失败时调用,会将Promise对象状态设置为失败,并且将失败的原因传递给对象,供then的回调函数使用
- 该函数有两个参数,resolve和reject,这两个参数同样也是函数形式
- Promise.then()函数具有两个参数,都是函数形式
- 第一个回调函数在Promise状态为成功时调用
- 其参数value是Promise的构造函数中回调函数中成功的结果
- 第二个回调函数在Promise状态为失败时调用
- 其参数reason是Promise的构造函数中回调函数中失败的原因
- 第一个回调函数在Promise状态为成功时调用
1.3 Promise实践
1.3.1 fs读取文件
基础回调函数形式:
- readFile的第一个参数是文件路径
- 第二个参数是一个回调函数,err表示出错信息,data表示获取到的数据
- 函数主体则根据参数进行操作即可
Promise封装后:
1.3.2 封装fs读取文件
用函数将fs读取操作封装
- 其返回一个Promise对象
调用函数,使用Promise.then()的方法
- 原始需要在readFile的参数里面指定回调函数
- 使用Promise后,可以在mineReadFIle后面的then函数中指定回调函数,解决回调地狱问题
1.3.3 util.promisify
作用:自动将异步操作封装成一个Promise
2. Promise属性
2.1 Promise 状态
状态:实例对象中的一个属性 【PromiseState】,三个值
- pending:待定,
- resolved/fullfilled:成功
- rejected:失败
状态改变
- 只能由pending改成resolved 或 pending改成rejected
- 状态只能改变一次
2.2 Promise 对象的值
- 实例对象中的另一个属性 【PromiseResult】
- 保存着异步任务【成功/失败】的结果
- 只有resolve、reject可以修改其值
3. Promise工作流程
- 调用构造函数前,Promise的状态为pending
- 调用构造函数,执行异步操作
- 成功则执行resolved(),修改Promise对象状态为resolved,在then函数中回调onResolved,返回一个新的Promise对象
- 失败则执行rejected(),修改Promise对象状态为rejected,在then函数中回调onRejected,返回一个新的Promise对象
4. 如何使用Promise
4.1 API
Promise构造函数:
Promise(executor){}
executor函数:执行器函数
(resolve,reject)=>{ }
- resolve函数:内部异步操作成功时我们调用的函数
value => { }
- reject函数:内部异步操作失败时我们调用的函数
reason => { }
PS!!!
executor会在Promise内部立即同步调用,意味着代码执行到Promise的对象创建时就会执行其构造函数的回调函数,再执行下面的代码
如这段代码先输出111再输出222
而执行器的异步操作,就在执行器中按照规定的异步顺序执行
- resolve函数:内部异步操作成功时我们调用的函数
Promise.prototype.then()方法:
(onResolved,onRejected)=>{ }
Promise.prototype.then()的prototype表示then是Promise的实例对象的方法,如果没有prototype则表示then是promise函数对象的方法(类似于静态方法)
- 参数为两个回调函数:
onResolved,onRejected
- onResolved函数:成功的回调函数:
(value)=>{ }
- onRejected函数:失败的回调函数:
(reason)=>{ }
- onResolved函数:成功的回调函数:
- 参数为两个回调函数:
Promise.prototype.catch()方法:
(onRejected)=>{ }
- 只指定异步操作失败的回调函数,参数只有onRejected
- onRejected函数:失败的回调函数:
(reason)=>{ }
- onRejected函数:失败的回调函数:
- 只指定异步操作失败的回调函数,参数只有onRejected
Promise.resolve方法:
(value)=>{ }
resolve是Promise类的静态方法,不需要实例就能调用
- 作用:接受一个参数,直接返回一个成功或失败的Promise对象,快速将一个值封装成一个Promise对象
- 使用:
- 特点:
- 如果传入的参数为非Promise对象,则返回的结果为状态为成功的Promise对象
- 如果传入的参数为Promise对象,则返回的结果为状态为传入的Promise对象的状态,返回结果的值为传入Promise的值
- 这边会报错是因为传入的Promise状态为rejected,这需要Promise有处理错误的回调函数,通过
P2.catch((reason)=>{} )
补上回调函数即可 - 相反,如果传入的Promise的状态为resolved,则不需要特意补一个回调函数也不会报错
- 这边会报错是因为传入的Promise状态为rejected,这需要Promise有处理错误的回调函数,通过
Promise.reject()方法:(reason)=>{}
- 作用:返回一个值为reason的,状态为rejected的Promise对象
- 无论传入什么都返回一个状态为失败Promise,即使传入一个成功的Promise对象,返回的Promise的值是传入的成功的Promise对象,但是返回Promise的状态还是失败
- 作用:返回一个值为reason的,状态为rejected的Promise对象
Promise.all方法:
(promises)=>{}
作用:返回一个新的Promise,当所有Promise都成功,返回的Promise状态为成功,其结果为所有Promise的结果组成的一个数组;当存在失败的Promise,返回的Promise的状态为失败,其结果为失败的Promise的结果
成功情况:
失败情况:
4.2 Promise的几个关键问题
4.3.1 改变Promise对象的状态
- 三种方式
- 在构造函数中直接调用
resolve
函数 - 在构造函数中直接调用
reject
函数 - 在构造函数中直接抛出错误:
throw Error
- 在构造函数中直接调用
4.3.2 一个Promise指定多个成功/失败的回调函数,都会调用吗
都会执行!
- 当p的状态变为resolve时,p指定的两个状态变为resolve的回调函数都会执行
4.3.3 改变Promise状态和指定回调函数谁先谁后
问题简化:Promise代码运行时,resolve先执行还是then先执行
注意,指定回调和执行回调函数是不一样的,指定回调类似于p.then()中声明有哪些回调函数,执行回调则是在状态确定之后执行之前指定的回调
两种情况都有可能
- 先改状态再指定回调:
- 执行器中是一个同步操作,那么就先做执行器中的操作再执行then语句即指定回调
- 例如直接在执行器中直接调用 resolve()/reject()
- 执行器中式一个异步操作,延长更长时间才调用then()同样可以达到效果
- 执行器中是一个同步操作,那么就先做执行器中的操作再执行then语句即指定回调
- 先指定回调再改变状态
- 执行器中式异步操作时,会先执行then,指定回调(但是不执行回调),再回头根据异步操作的顺序进行处理
什么时候能够得到数据?
- 如果先改变状态,那么当指定回调时,回调函数就会被调用,得到数据
- 如果先指定回调,那么当状态发生改变时,回调函数才被调用得到数据
例子:
- promise执行器中是一个异步任务,那么就执行then,指定回调;处理执行器中的异步任务,1000ms后改变状态;再执行成功的回调函数,得到数据
4.3.4 then()方法返回的Promise的对象的状态由什么决定
简单表达:由then()指定的回调函数执行的结果决定
详细表达:
如果回调函数抛出异常,返回Promise状态为【rejected】
如果then()有返回结果,且结果是非Promise对象,例如
则then()方法返回的Promise对象状态为【resolved】,其值为【返回值】,即521
如果then()有返回结果,且结果是Promise对象,例如
则其返回的Promise的状态和值由返回的Promise决定
4.3.5 Promise如何串联多个操作任务
Promise的then()返回一个新的Promise对象,可以形成then方法的链式调用,从而避免回调地狱
let p = new Promise((resolve, reject) => {// 第一次执行异步任务setTimeout(()=>{console.log("first mission")resolve("1000ms later resolve");},1000)})p.then(// 返回一个执行异步任务的Promise,从而第二次执行异步任务,再第一次执行完之后才能执行,链式调用避免回调地狱(value)=>{return new Promise((resolve, reject) => {setTimeout(()=>{console.log("second mission")resolve();},1000)})},).then(value => {return new Promise(resolve => {setTimeout(()=>{console.log("third mission")resolve();},1000)})})
4.3.6 Promise异常穿透?
当使用Promise的then的链式调用时,可以在最后指定失败的回调,而不用每个then都指定一个失败回调
但凡链式调用的过程中由出现失败的情况,最后都会调用最后的失败回调
例如:
then()方法中途返回一个失败的Promise,直接调用最后的catch指定的失败回调
4.3.7 中断Promise链
链式调用过程中,我们希望在某一个then()方法的onResolve回调函数调用过程中,中断Promise的链式调用,只需要返回一个状态为pending的Promise对象
当没有明确返回一个promise对象,then()也会返回一个Promise对象,状态为【resolved】,结果为【underfined】
因为then方法的回调函数调用依据是Promise的状态是resolved或者rejected,没有pending对应的回调函数,所以后面的都没法执行了
例如:
自定义封装看到P31
5. Promise自定义封装
6. async和await
6.1 async
async是一个函数修饰符
函数的返回值是Promise对象
Promise对象的结果由async函数执行的返回值决定
- 和then一样:分成三种情况执行返回值是非Promise对象,是一个Promise对象,是抛出异常
6.2 await
获取Promise的成功的结果
- await右侧表达式一般为Promise对象,但也可以是一个其他值
- 如果表达式时Promise对象,await返回的Promise成功的值
- 如果表达式是其他值,直接将此值作为await的返回值
6.3 async 和 await
理解:async是函数的修饰符,表示这个函数内部可能会存在异步操作;await是一个表达式修饰符,表达式一般跟Promise(内含异步操作),返回的值是Promise成功的值,并且await下面的代码必须要等await后的异步操作完成后才可继续执行,保证了时序
6.3.1 二者联系与区别
- await必须要卸载async函数中,async中可以没有await
- 如果await的Promise失败了,会抛出一个异常,需要try catch进行捕获处理
6.3.2 应用例子 — 发送axios请求
6.3.3 应用例子 — 读文件 + 闭包概念
需求:读取多个文件的内容,并将其拼接
使用回调函数的方式进行
所以console.log输出的时候可以访问到 data1和data2
async + await
- 首先导入util包,利用
util.promisify()
方法,将readfile方法转化成一个promise对象并返回
- 利用readfile的Promise对象,使用await修饰,返回文件内的内容给data,之后一次性拼接
- 优点
- 避免重复回调,可读性高
- 出错可以直接用一个大的try catch包裹,而不用每次回调都抛出错误
Extra:闭包
所以console.log输出的时候可以访问到 data1和data2
async + await
[外链图片转存中…(img-n9QLdX91-1662185609736)]
- 首先导入util包,利用
util.promisify()
方法,将readfile方法转化成一个promise对象并返回
[外链图片转存中…(img-WGeX8p3x-1662185609737)]
- 利用readfile的Promise对象,使用await修饰,返回文件内的内容给data,之后一次性拼接
- 优点
- 避免重复回调,可读性高
- 出错可以直接用一个大的try catch包裹,而不用每次回调都抛出错误
Extra:闭包
6.3.3 利用到了函数闭包:在上述代码中父对象的变量对于所有子对象都是可见的,反之则不成立;而在我的理解中,闭包是能够读取其他函数内部变量的函数。又因为JavaScript中只有函数内部的子函数才能够获取函数的局部变量,所以在JavaScript中,可以简单理解闭包为:在函数内部的函数
尚硅谷Web前端Promise教程从入门到精通——笔记相关推荐
- 尚硅谷Web前端ES6教程详细笔记,涵盖ES6-ES11
1 ES介绍 2 ES6的新特性 2.1 let关键字 2.1.1 声明变量 let a; let b,c,d; let e=100; let f=521,g="iloveyou" ...
- web前端全套教程,入门必备
WEB前端在编程界已经是非常根深蒂固,其发展也是异常宽广. 很多人选择WEB前端,可能是因为WEB前端容易入门,而且不需要太多专业基础.随着前端的人才越来越多,企业面试要求也越来越高,进阶高级前端需要 ...
- 尚硅谷web前端HTML5+CSS3笔记
目录 1尚硅谷-课程简介 2尚硅谷-网页简史 3尚硅谷-HTML简史 4尚硅谷-编写你的第一个网页 5尚硅谷-安装notepad++ 6尚硅谷-自结束标签和注释 7尚硅谷-标签中的属性 8尚硅谷-文档 ...
- 尚硅谷web前端工程师1000集学习笔记11
一个练习 <!doctype html> <html> <head> <meta charset="utf-8" ...
- web前端之html从入门到精通
前后台分离架构 目前,企业级web开发多采用前后台分离开发模式,这种模式要求前端开发者专注于前端开发,后端开发者专注于后端开发,各自完成自己擅长的任务模块. html介绍 HTML被称为超文本标记语言 ...
- 尚硅谷JavaScript基础实战丨JS入门到精通全套完整版 P15
P15 JavaScript运算符 **<!DOCTYPE html> <html><head><meta charset="utf-8" ...
- 推荐20个很有帮助的 Web 前端开发教程
在平常的搜索中,我碰到过很多有趣的信息,应用程序和文档,我把它们整理在下面这个列表.这是收藏的遇到的有用内容的一个伟大的方式,可以在你需要的时候方便查阅.相信你会在这个列表中发现对你很有用的资料. 您 ...
- 风云叱咤,尚硅谷云原生实战教程(下篇)发布
摘要:企业级容器云实战,真正实现云上亿级流量永不宕机! 若逢新雪初霁,满月当空. 他带笑向我们走来, 月色与雪色间,他是第三种绝色. 他浑身上下都是宝, 上知天文,下晓地理,中通人和, 他就是我们的老 ...
- 视频教程-最新完整VUE前端教程从入门到精通,纯干货企业级项目实战-Vue
最新完整VUE前端教程从入门到精通,纯干货企业级项目实战 10年以上开发经验,曾经是八维教育实训主任,千峰教育高级HTML5前端讲师,尚品中国创始人.现任程序思维创始人.曾和大厂.国企等大型企业合作开 ...
最新文章
- 如何用git命令行上传本地代码到github
- 米家扩展程序初始化超时_28条规范和建议,教你如何设计出一套完美的PLC程序...
- 用matlab解公式,怎么用matlab解这个公式A MATLAB script that solves the differential e
- css表格文字超数量就竖排_求助!!一个非常棘手的问题。就是文字竖排显示的问题...
- unity实现图片轮播效果_Unity实现图片轮播组件
- LeetCode 1668. 最大重复子字符串
- Java 目录操作二(获取文件的上级目录、获取目录最后修改时间、打印目录结构、遍历指定目录下的所有目录)
- MovieClip实现拖拽等移动位置的功能
- 对于局部变量_浅谈Shell函数中全局变量和局部变量
- 100个常用的Linux命令
- 阅读SQL语言艺术实践一
- CentOS 配置httpd使局域网能够正常訪问
- 一篇文章看懂什么是无服务器架构
- Managing Configuration Data Programmatically in ASP.NET 2.0
- Win7动态主题制作
- h5拍摄身份证_H5接口调用,身份证识别
- Docker 自动启动和容器自动启动
- python抢购软件/插件/脚本附完整源码
- 容器如何访问外部世界?- 每天5分钟玩转 Docker 容器技术(36)
- 简单入门CDQ分治(很有意思的算法)
热门文章
- 没什么经验的UE/UI设计师如何应对面试
- 笔记-项目干系人管理-识别干系人
- 【图文保存为图片并下载到相册】海报 h5, 微信和 ios 不支持 和 用uniapp 微信小程序 使用canvas把页面转为图片保存到手机
- 大兴线各站名均有特殊含义,给大家普及一下!
- 数字图像与机器视觉基础补充(2)--颜色转换+分割车牌
- 程序员有了这几款神器,瞬间逼格就上去了!
- 2015年中国最具竞争力机器人控制器企业10强
- java模拟国际象棋游戏_Javafx实现国际象棋游戏
- SpringBoot 实现 QQ邮箱注册和登录
- kafka集群搭建教程(使用自带的zookeeper)