1. Promise简介

1.1 Promise理解

  • 抽象理解:Promise是js中进行异步编程的新解决方案

    • 异步编程:自己的理解:需要按照一定顺序进行的编程

      • fs,文件操作
      • ajax
      • 数据库操作
      • 定时器
    • 之前进行异步编程直接通过回调函数的方式进行,会导致回调地狱
      • 回调函数:作为参数的函数
      • 回调地狱:回调函数里面嵌套回调函数
        • 代码可读性差
        • 不便于异常处理
  • 具体理解:
    • 从语法上说,Promise是一个构造函数
    • 从功能上说,Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值
  • 为什么使用Promise
    • Promise支持链式调用,可以解决回调地狱问题

      • 回调地狱:
    • 指定回调函数

1.2 Promise初体验

  • Promise是一个对象,包含成功、失败等状态,构造函数,then等方法
  • Promise构造函数的参数是一个包含异步操作的函数
    • 该函数有两个参数,resolve和reject,这两个参数同样也是函数形式

      • resolve在函数内的异步操作成功时调用,会将Promise对象状态设置为成功,并且将成功的结果传递给对象,供then的回调函数使用
      • reject在函数内的异步操作失败时调用,会将Promise对象状态设置为失败,并且将失败的原因传递给对象,供then的回调函数使用
  • Promise.then()函数具有两个参数,都是函数形式
    • 第一个回调函数在Promise状态为成功时调用

      • 其参数value是Promise的构造函数中回调函数中成功的结果
    • 第二个回调函数在Promise状态为失败时调用
      • 其参数reason是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

      而执行器的异步操作,就在执行器中按照规定的异步顺序执行

  • Promise.prototype.then()方法: (onResolved,onRejected)=>{ }

    Promise.prototype.then()的prototype表示then是Promise的实例对象的方法,如果没有prototype则表示then是promise函数对象的方法(类似于静态方法)

    • 参数为两个回调函数: onResolved,onRejected

      • onResolved函数:成功的回调函数:
        (value)=>{ }
      • onRejected函数:失败的回调函数:
        (reason)=>{ }
  • Promise.prototype.catch()方法:(onRejected)=>{ }

    • 只指定异步操作失败的回调函数,参数只有onRejected

      • onRejected函数:失败的回调函数:
        (reason)=>{ }
  • Promise.resolve方法:(value)=>{ }

    resolve是Promise类的静态方法,不需要实例就能调用

    • 作用:接受一个参数,直接返回一个成功或失败的Promise对象,快速将一个值封装成一个Promise对象
    • 使用:
    • 特点:
      • 如果传入的参数为非Promise对象,则返回的结果为状态为成功的Promise对象
      • 如果传入的参数为Promise对象,则返回的结果为状态为传入的Promise对象的状态,返回结果的值为传入Promise的值
        • 这边会报错是因为传入的Promise状态为rejected,这需要Promise有处理错误的回调函数,通过P2.catch((reason)=>{} )补上回调函数即可
        • 相反,如果传入的Promise的状态为resolved,则不需要特意补一个回调函数也不会报错
  • Promise.reject()方法:(reason)=>{}

    • 作用:返回一个值为reason的,状态为rejected的Promise对象

      • 无论传入什么都返回一个状态为失败Promise,即使传入一个成功的Promise对象,返回的Promise的值是传入的成功的Promise对象,但是返回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,指定回调(但是不执行回调),再回头根据异步操作的顺序进行处理

什么时候能够得到数据?

  • 如果先改变状态,那么当指定回调时,回调函数就会被调用,得到数据
  • 如果先指定回调,那么当状态发生改变时,回调函数才被调用得到数据

例子:

  • 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教程从入门到精通——笔记相关推荐

  1. 尚硅谷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" ...

  2. web前端全套教程,入门必备

    WEB前端在编程界已经是非常根深蒂固,其发展也是异常宽广. 很多人选择WEB前端,可能是因为WEB前端容易入门,而且不需要太多专业基础.随着前端的人才越来越多,企业面试要求也越来越高,进阶高级前端需要 ...

  3. 尚硅谷web前端HTML5+CSS3笔记

    目录 1尚硅谷-课程简介 2尚硅谷-网页简史 3尚硅谷-HTML简史 4尚硅谷-编写你的第一个网页 5尚硅谷-安装notepad++ 6尚硅谷-自结束标签和注释 7尚硅谷-标签中的属性 8尚硅谷-文档 ...

  4. 尚硅谷web前端工程师1000集学习笔记11

    一个练习 <!doctype html> <html>     <head>         <meta charset="utf-8" ...

  5. web前端之html从入门到精通

    前后台分离架构 目前,企业级web开发多采用前后台分离开发模式,这种模式要求前端开发者专注于前端开发,后端开发者专注于后端开发,各自完成自己擅长的任务模块. html介绍 HTML被称为超文本标记语言 ...

  6. 尚硅谷JavaScript基础实战丨JS入门到精通全套完整版 P15

    P15 JavaScript运算符 **<!DOCTYPE html> <html><head><meta charset="utf-8" ...

  7. 推荐20个很有帮助的 Web 前端开发教程

    在平常的搜索中,我碰到过很多有趣的信息,应用程序和文档,我把它们整理在下面这个列表.这是收藏的遇到的有用内容的一个伟大的方式,可以在你需要的时候方便查阅.相信你会在这个列表中发现对你很有用的资料. 您 ...

  8. 风云叱咤,尚硅谷云原生实战教程(下篇)发布

    摘要:企业级容器云实战,真正实现云上亿级流量永不宕机! 若逢新雪初霁,满月当空. 他带笑向我们走来, 月色与雪色间,他是第三种绝色. 他浑身上下都是宝, 上知天文,下晓地理,中通人和, 他就是我们的老 ...

  9. 视频教程-最新完整VUE前端教程从入门到精通,纯干货企业级项目实战-Vue

    最新完整VUE前端教程从入门到精通,纯干货企业级项目实战 10年以上开发经验,曾经是八维教育实训主任,千峰教育高级HTML5前端讲师,尚品中国创始人.现任程序思维创始人.曾和大厂.国企等大型企业合作开 ...

最新文章

  1. 如何用git命令行上传本地代码到github
  2. 米家扩展程序初始化超时_28条规范和建议,教你如何设计出一套完美的PLC程序...
  3. 用matlab解公式,怎么用matlab解这个公式A MATLAB script that solves the differential e
  4. css表格文字超数量就竖排_求助!!一个非常棘手的问题。就是文字竖排显示的问题...
  5. unity实现图片轮播效果_Unity实现图片轮播组件
  6. LeetCode 1668. 最大重复子字符串
  7. Java 目录操作二(获取文件的上级目录、获取目录最后修改时间、打印目录结构、遍历指定目录下的所有目录)
  8. MovieClip实现拖拽等移动位置的功能
  9. 对于局部变量_浅谈Shell函数中全局变量和局部变量
  10. 100个常用的Linux命令
  11. 阅读SQL语言艺术实践一
  12. CentOS 配置httpd使局域网能够正常訪问
  13. 一篇文章看懂什么是无服务器架构
  14. Managing Configuration Data Programmatically in ASP.NET 2.0
  15. Win7动态主题制作
  16. h5拍摄身份证_H5接口调用,身份证识别
  17. Docker 自动启动和容器自动启动
  18. python抢购软件/插件/脚本附完整源码
  19. 容器如何访问外部世界?- 每天5分钟玩转 Docker 容器技术(36)
  20. 简单入门CDQ分治(很有意思的算法)

热门文章

  1. 没什么经验的UE/UI设计师如何应对面试
  2. 笔记-项目干系人管理-识别干系人
  3. 【图文保存为图片并下载到相册】海报 h5, 微信和 ios 不支持 和 用uniapp 微信小程序 使用canvas把页面转为图片保存到手机
  4. 大兴线各站名均有特殊含义,给大家普及一下!
  5. 数字图像与机器视觉基础补充(2)--颜色转换+分割车牌
  6. 程序员有了这几款神器,瞬间逼格就上去了!
  7. 2015年中国最具竞争力机器人控制器企业10强
  8. java模拟国际象棋游戏_Javafx实现国际象棋游戏
  9. SpringBoot 实现 QQ邮箱注册和登录
  10. kafka集群搭建教程(使用自带的zookeeper)