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 进行处理 【麻烦不建议】
for await (variable of iterable) {
statement
}
for...of循环用于遍历同步的 Iterator 接口。新引入的for await...of循环,则是用于遍历异步的 Iterator 接口- 原生具备 Iterator 接口的数据结构如下。
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
- 对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的,需要开发者手动指定
- 原生具备 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 结果