Promise

-

Promise的理解和应用

promise是什么

理解

  • 抽象表达
    1. promise是一门新的技术(ES6规范)
    2. promise是js中进行异步编程的新解决方案(旧方案是单纯使用回调函数)
  • 具体表达
    1. 从语法上来说:promise是一个构造函数
    2. 从功能上来说:promise对象用来封装一个异步操作并可以获取成功和失败的结果值

      promise的状态

  • 实例对象的一个属性PromiseState
    1. pending 未决定的 
    2. resolved/fullfillled 成功
    3. rejected 失败
  • promise对象的状态只改变一次

    promise对象的值

  • 实例对象中的另一个属性PromiseResult
  • 保存着异步任务成功/失败的结果
  • 无论变为成功还是失败 , 都会有一个结果数据
  • 成功的结果数据一般称为 value, 失败的结果数据一般称为 失败的结果数据一般称为 reason

    promise的基本流程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <script>

    // 1) 创建promise对象(pending状态), 指定执行器函数
    const p = new Promise((resolve, reject) => {
    // 2) 在执行器函数中启动异步任务
    setTimeout(() => {
    const time = Date.now()
    // 3) 根据结果做不同处理

    if (time % 2 === 1) {
    resolve('成功的值 ' + time)
    } else {
    reject('失败的值' + time)
    }
    }, 2000)})


    p.then(
    value => {
    console.log('成功的value: ', value)
    },
    reason => {
    console.log('失败的reason: ', reason)
    }
    )
    </script>

为什么要用promise

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

  1. 什么是回调地狱
    • 回调函数嵌套调用,外部回调函数异步执行的结果 是嵌套的回调执行的条件
  2. 回调地狱的缺点
    • 不便于阅读
    • 不便于异常处理
  3. 解决方案
    promise链式调用
  4. 终极解决方案
    async/await

如何使用promise

API

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

    • executor(执行器)函数 : 把promise对象的参数叫做执行器函数: (resolve, reject) => {}
      • 执行器函数会在promise内部立即同步调用,then方法是异步调用的
    • resolve函数 : 内部定义成功时我们调用的函数 value => {}
    • reject函数 : 内部定义失败时我们调用的函数 reason => {}
  2. Promise.prototype.then方法 : (onResolved, onRejected) => {}

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

    • onRejected函数 : 失败的回调函数 (reason) => {}
    • 说明:then方法的语法糖,相当于 相当于 : then(undefined, onRejected)
  4. Promise.resolve方法 : (value) => {}

    • value:成功的数据或 promise对象
    • 说明 :返回一个成功 /失败的 promise对象
  5. Promise.reject方法 : (reason) => {}

    • reason: 失败的原因
    • 说明 : 返回一个失败的 promise对象
  6. Promise.all方法 : (promises) => {}

    • promises: 包含 n个 promise的数组 的数组
    • 说明 : 返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败
  7. Promise.race方法 : (promises) => {}

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

    • 可以将一般的回调函数转化成返回promise对象的函数

promise的几个关键问题

  1. 如何改变promise的状态

    • resolve(value): 如果当前是 pending就会变为 resolved
    • reject(reason): 如果当前是 pending就会变为 rejected
    • 抛出异常 : 如果当前是 pending就会变为 rejected
  2. 一个promise对象指定多个成功/失败的回调函数,都会调用吗

    • 当promise的状态改变为相应状态时都会调用
  3. 改变promise状态和指定回调函数谁先谁后

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

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

    • promise的then返回一个新的promise,可以看成then()的链式调用
    • 通过then的链式调用串联多个异步或同步任务
  6. promise异常穿透

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

    • 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
    • 办法:在回调函数中返回一个pendding状态的promise对象return new Promise(()=>{})

async和await

async函数

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

await表达式

  1. await右侧的表达式一般为promise对象,但也可以是其他值
  2. 如果表达式是promise对象,await返回的是promise成功的值
  3. 如果表达式是其他值,直接将此值作为await的返回值
  • await必须写在async函数中,但async函数中可以没有await
  • 如果await的promise失败,就会抛出异常,需要通过try catch捕获处理