概述

promise是什么

  • 抽象表达:Promise是JS中异步编程的解决方案之一
  • 具体表达:Promise是一个构造函数,promise实例用来封装异步操作,并获取结果

promise的优势

  1. 指定回调更加灵活
    • promise会在异步任务完成后,保存状态和结果
    • 因此可以在异步任务完成之后,再指定回调,并立刻异步执行
    • 旧的方式必须在异步任务启动前指定
  2. 支持链式调用
    • 可以解决回调地狱问题

promise的劣势

  1. 无法直接获得promise当前的状态

基本语法

  1. const promise = new Promise((resolve, reject) => {
  2. $.http({
  3. success (res) {
  4. resolve(res.data)
  5. },
  6. error (error) {
  7. resolve(error)
  8. }
  9. })
  10. })
  • 使用 Promise 构造函数创建实例
    • 接收一个回调,叫做执行器函数(executor),在其中执行异步操作;执行器函数是同步回调
  • 回调会有两个参数,都是函数,用于修改promise的状态,并传递异步任务的结果
    • resolve()修改为fulfilled
    • reject()修改为rejected
    • 调用时都能传入一个参数,参数会作为Promise的值,reject 推荐传入一个 Error 实例
    • 传入的参数可以是一个新的promise,所属promise会使用这个promise的状态和值

状态

每个promise都有状态,并会根据状态执行不同操作

  • pending:等待,promise初始状态,正在执行异步操作
  • fulfilled:已完成,执行onResloved
  • rejected:已拒绝,执行onRejected

一个promise对象只能改变一次状态,且只能从pending -> fulfilled/rejected

指定回调

  1. promise
  2. .then(result => result)
  3. .catch(error => error)
  4. .finally(() => 'finally')

因为promise是有状态的,因此回调也被分为两种

  • onResloved:成功的回调,fulfilled状态调用,用于获取结果
  • onRejected:失败的回调,rejected状态调用,用于捕获错误

回调调用规则

  1. promise1.then(value => console.log(value + '1'))
  2. promise1.then(value => console.log(value + '2'))
  3. promise1.catch(error => error).then(value => console.log(value + '3'))

可以通过promise的then/catch/finally方法,添加回调

  1. 一个promsie可以调用多次then/catch/finally,给同一状态添加多个回调
  2. 如果promise状态还未改变时添加回调,promsie会将回调保存起来
  3. 当promise状态发生改变,就会按照添加的顺序,将回调添加进任务队列中等待执行
  4. promise状态改变完成后再添加回调,会立刻将该回调添加进任务队列中 灵活性

浏览器中,如果promise变为rejected,而且没有添加任何一个onRejected回调,就会在控制台打印错误。

Promise.prototype.then()

  1. Promise.prototype.then(onResloved, onRejected)
  • 用于给promise指定回调,可同时添加两个状态的回调
  • 返回一个新的promsie,状态与值根据回调的执行结果决定
    • 回调返回promise,该promsie的状态和值会成为新promise的
    • 回调返回非promise得任意值,新promise状态变为fulfilled,值为返回的值
    • 回调中抛出错误,新promise状态变为rejected,值为抛出的异常信息
    • 如果返回的promise一直处于pending状态,调用链会中断 中断promise链
  • 参数有默认行为,如果某个参数没有收到值,或者值是非函数,就会将默认行为推入对应的回调队列中
    • onResloved:直接将结果返回 value => value
    • onRejected:直接将结果作为错误抛出 reason => throw reason 错误穿透

Promise.prototype.catch()

  1. Promise.prototype.catch(onRejected)
  • 用于给promise指定回调,只能添加onRejected
  • 返回值同then

本质上是then的语法糖

  1. promise.catch(undefined, onRejected)

Promise.prototype.finally()

  1. Promise.prototype.finally(callback)
  • ES9新增方法,用于给promise指定回调,只接收一个回调
  • 该方法会将回调,同时添加到两个状态的回调队列中
    • 因此不论上一个promsie成功还是失败,这个回调都会执行
    • finally的回调没有参数,如果没有传递回调,也不会有任何影响
    • 该API用于做公共的收尾工作,因为Promise无法直接获取状态,使用 finally 可以节省代码
  • 返回一个新的promise,状态与值和上一个promise相同
    1. Promise.resolve('成功').finally(() => console.log('我是finally'))
    2. Promise.reject(new Error('失败')).finally(() => console.log('我是finally'))

本质上是then的语法糖

  1. promise.then(
  2. result => {
  3. callback()
  4. return result
  5. },
  6. error => {
  7. callback()
  8. throw error
  9. }
  10. )

静态方法

Promise.all(全部成功)

Promise.all(iterable)
  • iterable:可迭代对象
    • 内部元素应该是promise,非promise元素会被直接封装为一个成功的 promsie
  • 使用:等待 iterable 中的promise完成,并返回一个新的promise,新promise的状态与值取决于方法
  • 所有的promise都成功才成功,只要有一个失败就直接失败
    • 成功:结果是个数组,顺序和promise数组一致,下标一一对应
    • 失败:结果就是那个失败的promise的结果

Promise.allSettled(全部完成)

Promise.allSettled(iterable)
  • 使用同 all
  • 返回promise状态总是会成功的,能得到值中所有promise的结果和状态
  • 最终结果是一个数组,每个元素都是一个对象,按照参数顺序封装了对应promise的状态和结果
    • status:状态,
      • rejected:失败的
      • fulfilled:成功的
    • reason:失败时的结果字段
    • value:成功时的结果字段

Promise.race(第一个完成)

Promise.race(iterable)
  • 使用同 all
  • 使用第一个完成的 promise 的状态和值
  • 如果 iterable 中包含了非 promise 元素,则 race 方法会直接成功并使用该元素作为值

Promise.any(第一个成功)

Promise.any(iterable)
  • 使用同 all
  • 任意一个promise成功就成功,且使用那个 promise 的值,全部失败才失败,值是一个错误对象

Promise.resolve/reject

Promise.resolve(value)
Promise.reject(error)
  • 返回一个成功/失败的promise
  • resolve可以传入promise,新promise的状态结果等同于传入的;reject不可以

自己实现Promise

selfPromise.js