Promise知识点总结

75 阅读6分钟

Promise基本信息

什么是Promise

Promise是一门新的技术(ES6规范),是JS异步编程的新的解决方案(旧的方案是使用回调函数)

  • 从语法上来说:Promise是一个构造函数
  • 从功能上来说:promise对象用来封装一个一不糙做并且可以获取其成功失败的结果值

异步编程包括但不限于以下几种

  • fs文件操作 require('fs').readFile('./index.html,(err,data)=>{})
  • 数据库操作(Mongodb...)
  • Ajax $.get('/server',(data)=>{})
  • 定时器

常用的实践练习加深理解

  • Promise实例化,参数是一个函数,参数是resolve和reject,参数内异步函数,然后成功执行resolve,失败执行reject。然后就调用Promise的then方法,来输出结果。 image.png

  • Promise实践练习-fs读取文件 image.png

  • Promise实践练习-AJAX请求 image.png

    image.png

  • nodejs的util.promisify方法进行promise风格的封装 image.png

  • 封装AJAX image.png image.png

Promise的状态改变

  1. pending变为resolved/fullfiled
  2. pending变为rejected 说明:只有这两种,而且一个promise对象只能改变一次,无论变为成功还是失败都只能改变一次,不能从失败转成功,或者从成功变失败

Promise对象中有一个属性叫做PromiseState,这个就是Promise对象的状态,那么这个属性有几种状态测存在呢?总共有一下三种:

  • pending 未决定的
  • resolved / fulfilled 成功
  • rejected 失败

Promise的基本流程

image.png

为什么使用Promise

1.支持链式调用,可以解决回调地狱的问题

  • 什么是回调地狱 回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
  • 回调地狱的缺点 不便于阅读,不便于异常处理 2.指定回调函数的方式更加灵活:回调函数的方式必须在启动异步任务之前制定,但是promise:启动异步任务=》返回promise对象=〉给promise对象绑定回调函数(甚至可以在异步任务结束后指定) 3.解决方案 Promise链式调用 4.终极解决方案

Promise常用API

  1. Promise构造函数:Promise(excutor){}

    • excutor函数:是执行器(resolve,reject)=>{}
    • resolve函数:内部定义成时候我们调用的函数 valve=>{}
    • reject函数:内部定义失败时候,我们调用的函数 reason=>{} 说明:excutor会在Promise内部立即同步调用,异步操作在执行器中执行
  2. Promise.prototype.then方法(onResolved,onRejected)=>{}

    • onResolved函数:成功的回调函数(valve)=>{}
    • onRejected函数:失败的回调函数(reason)=>{} 说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的Promise对象
  3. Promise.prototype.catch方法

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

    • value:成功的数据或者promise对象,返回一个成功/失败的promise对象 image.png
  5. Promise.reject函数 方法:(reason)=>{}, 无论你传入什么,字符还是promise对象,结果都是失败的

    image.png image.png

  6. Promise.all 方法 (promises)=>{}

    • promises:包含n个promise的数组,返回一个新的promise,只有所有的promise都成功才会成功,只要有一个失败了就直接失败

    image.png

    image.png

    image.png

    image.png

  7. Promise.race 方法(promises)=>{}

    • promises:包含n个promise的数组,返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态

    image.png 由于p1先完成,所以结果就是p1的 image.png

    image.png 肯定不是p1,应该是p2

Promise关键的问题

  1. 在代码中如何改变promise的状态

    • 调用resolve函数,可以将状态pending=>fullfilled(resolved)
    • 调用reject函数,可以将状态pending=>rejected
    • throw抛出异常:如果当前是pending就会变成reject
  2. 一个promise指定多个成功/失败回调函数,都会调用吗? 在这里就是then()方法当promise改变为对应状态的时候就会调用,但是如果状态不变的话就不会调用,比如,我们注释掉下图中的resolve('OK') image.png

  3. 改变状态和指定回调函数谁先谁后(也就是resolve/reject先执行,还是then先执行)

    • 都有可能,正常情况下是先指定回调函数再改变状态,但是也可以先改变状态再指定回调函数,
    • 如何先改变状态再指定回调(1)在执行器中直接调用resolve/reject函数(当执行器中的函数是同步函数的时候,就先改变状态resolve/reject,再执行回调then)(2) 延长更长时间才调用then(比如执行器中延长一秒执行resolve,但是可以设置2秒后再执行then)
    • 什么时候才能得到数据,也就是回调函数什么时候执行(1)如果先指定的回调函数,那么当状态发生改变的时候,回调函数就会调用,得到数据,(2)如果先改变的状态,那么当指定回调函数时,回调函数就会调用,得到数据
  4. Promise.then()返回新的promise的结果状态由什么决定

    • 简单表达就是由then指定的回调函数执行的结果决定
    • 详细表达就是(1)如果抛出异常,新promise变为reject,reason为抛出的异常(2)如果返回的是非promise的任意值,那么新promise变为resolved,value为返回的值,(3)如果返回的是另一个新promise,此promise的结果就会成为新promise的结果
  5. promise如果串联多个操作任务

    • promise的then返回一个新的promise,可以开成then的链式调用
    • 通过then链式调用串联多个同步/异步任务 image.png
  6. Promise异常穿透

    • 当使用promise的then链式调用时,可以在最后指定失败的回调
    • 前面任何操作出了异常,都会传到最后失败的回调中处理 image.png
  7. 中断promise链

    • 当使用promise的then链式调用时,在中间中断,不再调用后面的then方法多,有且只有一个方式,就是return一个pending的promise对象 image.png

Promise自定义封装(手写Promise)

转发一篇手写promise文档:juejin.cn/post/699459…

async 和 await

async函数

  1. 函数的返回值为promise对象

  2. promise对象的结果由async函数执行的返回值决定

    image.png

await

  1. await右侧的表达式一般为promise对象,但是也可以是其他的值

  2. 如果表达式是promise对象,await返回的就是promise成功的值

  3. 如果表达式是其他值,直接将此值作为await的返回值

    image.png

注意:1.await必须卸载async函数中,但是async函数中可以没有await 2. 如果await的promise失败了,就会抛出异常,需要通过try..catch来捕获处理

参考视频:尚硅谷Web前端Promise教程从入门到精通