JS中的异步编程: Promise async/await

125 阅读3分钟
  1. 异步与同步
  • 同步行为:指令按顺序执行
  • 异步行为:顺序指令被中断(例如定时器触发,将回调插入队列)
  1. 原有的异步编程
  • 利用回调:在异步操作中提供成功和失败相对应的回调函数,异步操作需要另一个异步操作提供的返回值时生成回调地狱,不可取。
  1. Promise类
  • Promise可以理解为对未知结果(异步操作)的一个替代品,可以抽象地表示异步操作。
  • 实例化:需要传入执行器函数
let example = new Promise(()=>{})
  • 执行器函数:有两个参数,分别为resolve和reject函数,调用resolve()会将状态切换为resolved,调用reject()会将状态切换为rejected。
    • 作用:a.初始化promise的异步行为 b.控制状态
    • 注意:执行器函数是同步执行的,状态的转换不可撤销
new Promise((resolve, reject) => {})
  • 状态:pending resolved rejected,promise的状态是私有的,无法通过try/catch捕获到,因为同步和异步是两种模式。
  • promise既是一个同步对象,也是异步执行模式的媒介。
  • 静态方法:
    • Promise.resolve():实例化一个状态为resolved的promise实例,其值为传入的第一个参数,需要注意的是若参数为promise,则相当于空包装
    • Promise.reject():实例化一个状态为rejected的promise实例,抛出的异步错误为传入的第一个参数,需要注意的是若参数为promise,则错误的理由为传入的promise
  • 实例方法:
    • Promise.prototype.then():用于给promise实例添加处理程序,返回一个新的promise实例,这个新promise实例是通过Promise.resolve()包装的,所传的参数是onResolved或者onRejected函数的返回值。
    //接收两个参数(均可选)第一个是onResolved函数,在promise进入resolved状态时调用,第二个是onRejected函数,在promise进入rejected状态时调用。
    //如果只需一个,另一个参数用null占位。
    Promise.prototype.then(onResolved, onRejected)
    
    • Promise.prototype.catch():用于给promise实例添加拒绝处理程序,本质上是语法糖。
    //只接受一个参数,onRejected函数
    //本质上与Promise.prototype.then(null, onRejected)相同
    Promise.prototype.catch(onRejected)
    
    • Promise.prototype.finally():resolved或rejected状态都会执行其回调并返回一个新的promise实例
  • 执行顺序:1.同步(注意:Promise实例化时的执行器函数也是同步) 2.在队列中的异步
  • 使用错误对象使promise状态变为rejected:在执行器函数或后续处理程序中返回错误对象
new Promise((resolve, reject) => reject(Error('msg')))
new Promise((resolve, reject) => {throw Error('msg')})
Promise.resolve().then(() => {throw Error('msg')})
  1. 链式调用
  • 利用promise实例方法返回新promise实例的特性,串联异步任务
  • 补充两个静态方法:
    • Promise.all():当一组promise全部完成时返回一个完成的promise,当组内有一个拒绝的promise出现时,合成promise状态为拒绝。
    //参数为可迭代对象,其中元素通过Promise.resolve()包装为promise
    //若全部完成,返回的合成promise的解决值为这一组所有解决值的数组
    Promise.all([])
    
    • Promise.race():返回一个包装的promise,是一组promise中最先落定的promise的镜像
    //参数为可迭代对象,其中元素通过Promise.resolve()包装为promise
    Promise.race([])
    

P.S. Promise方法手写见:juejin.cn/post/711159…

  1. 异步函数:async/await语法
  • 将promise应用于函数
  • async用于声明异步函数,但整体函数还是同步执行的
  • async函数中如果有返回值,则一定是一个promise对象,如果不是的话会默认被Promise.resolve()包装。
  • await在async函数中使用,运行至await关键字时异步函数被暂停执行,让出主线程,等到await后面的内容可用了,向消息队列中推送任务,该任务会恢复异步函数的执行。
  • 异步函数中可使用sleep()方法,实现非阻塞的暂停,参数是number,单位是毫秒。
  • 异步函数中可以并发地开启多个promise,提升效率
  • 异步函数的栈追踪信息可以清晰地指向函数,并提升性能(相对于不使用异步函数的代码)