跳到主要内容

generator和async/await

generator​

  • generator可以函数进行中断和恢复执行,这是它能封装异步任务的根本原因
  • generator最大的特点就是可以交出函数的执行权 (暂停执行)
    • 可以通过generator 处理优先级高的任务,通过判断是否有优先级高的任务,如果有,则通过yield来中断任务
    • 再通过next方法来恢复执行
  • generator可以控制异步任务管理
  • 可以分段执行,可以中断,恢复
  • 可以控制每个阶段的返回

场景:

  • 封装异步任务,管理异步任务的执行,可以处理优先级高的任务

generator是如何做到中断和恢复的?​

  • Generator 函数执行时会返回一个 Generator 对象,该 Generator 对象可以通过 next 方法来控制 Generator 函数的执行过程,并且可以通过 yield 表达式来暂停和恢复 Generator 函数的执行

Generator 函数可以通过 yield 表达式来暂停执行,next 方法来恢复执行, 并且可以通过 next 方法来控制 Generator 函数的执行过程

generator优缺点?​

优点:

  • 可以暂停和恢复执行。Generator 函数可以通过 yield 表达式来暂停执行,并且可以通过 next 方法来恢复执行
    • 可以在复杂的程序中实现更好的控制和调试
  • 可以实现迭代器和协程。
    • 迭代器:Generator 函数可以通过 yield 表达式来返回多个值,并且可以通过 next 方法来传入参数,这样可以实现类似迭代器的功能
    • 协程:Generator 函数还可以通过 yield* 表达式来调用另一个 Generator 函数,这样可以实现类似协程的功能

缺点:

  • 可读性和维护难度较高

  • 执行效率较低。由于 Generator 函数可以暂停和恢复执行,并且可以通过 yield 表达式来返回多个值,所以 Generator 函数可能会比较耗时和资源,导致执行效率较低

async/await​

  • await解决了promise.then链式调用的嵌套地狱的问题

  • 节省代码,不再需要写then,避免了嵌套代码

  • 使得异步操作变得更加方便

  • async其实就是 Generator 函数的语法糖

    • async函数就是将 Generator 函数的星号(*)替换成 async,将 yield替换成 await
      • 注意yiled只会等待后面的表达式的结果,表达式里面如果还存在异步操作,则不会等待
  • async和 await,比起Generator生成器星号和 yield,语义更清楚了

  • async函数的返回值是 Promise 对象, async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而 await命令就是内部 then命令的语法糖。

async await的原理是什么?​

  • 基本原理是将异步操作以同步操作的方式表示出来,使代码更加简洁易读
  • Async/await 的实现原理与 JavaScript 中的 Promises 相似,它也是基于回调函数实现的。

async 函数会返回一个 Promise 对象,这个 Promise 对象会在 async 函数内部执行完毕后被 resolve。然后,当 await 表达式遇到时,async 函数会暂停执行,并等待表达式的 Promise 对象被 resolve。当表达式的 Promise 对象被 resolve 时,async 函数会恢复执行,并将表达式的值作为结果返回。

循环中async 与 await的问题​

  • 不能在forEach、map、filter 和 reduce使用async/await, 否则会出问题
    • 原因很简单,那就是 forEach 只支持同步代码 !!
    • forEach 只是简单的执行了下回调函数而已,并不会去处理异步的情况
  • for...of能支持async/await, 但是for...in不可以!!
    • for…of 内部处理的机制和 forEach 不同,forEach 是直接调用回调函数,for…of 是通过迭代器的方式去遍历,forEach内部是没有迭代器的

总结:

  • 若想连续执行await,请使用没有回调的循环
    • 使用for...of,for,while循环
  • 永远不要和forEach一起使用await
  • 不要在 filter 和 reduce 中使用 await,如果需要,先用 map 进一步骤处理,然后在使用 filter 和 reduce 进行处理 【麻烦不建议】
text
for await (variable of iterable) {
statement
}
  • for...of循环用于遍历同步的 Iterator 接口。新引入的for await...of循环,则是用于遍历异步的 Iterator 接口
    • 原生具备 Iterator 接口的数据结构如下。
      • Array
      • Map
      • Set
      • String
      • TypedArray
      • 函数的 arguments 对象
      • NodeList 对象
    • 对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定

async/await, generator, promise这三者的关联和区别是什么?​

区别:

  • async/await 仅能用于处理 Promise 对象,对于其他类型的异步操作,仍需要使用回调函数或者其他方法

  • Generator 和 Promise 则比 async/await 更加灵活,它们都能够用于处理不同类型的异步操作,例如回调函数和事件监听等,但 Generator 和 Promise 都需要手动管理暂停和恢复的过程,并且需要使用回调函数或者链式语法来实现异步操作,对于简单的异步操作可能会增加代码的复杂度

关联:

  • async/await,它是基于 Generator 和 Promise 的语法系统,使用起来更加简洁优雅
    • 因此可以在async/await中使用 Generator 和 Promise 的特性来实现异步编程
    • async/await 中的 await 表达式可以用于等待 Generator 函数中 yield 表达式的返回值
    • async/await 中的 await 表达式可以用于等待 Promise 对象的 resolve 结果。
  • Generator 函数可以通过 yield* 表达式来调用另一个 Generator 函数。
  • Generator 函数来也可以处理 Promise 对象,并利用 yield 表达式来等待 Promise 对象的 resolve 结果