- 定义:封装多个内部状态的异步编程解决方案
- 形式:调用Generator函数(该函数不执行)返回指向内部状态的指针对象(不是运行结果)
- 声明:function* Func() {}
- 方法
next():使指针移向下一个状态,返回{ done, value }(入参会被当作上一个yield命令表达式的返回值)
return():返回指定值且终结遍历Generator函数,返回{ done: true, value: 入参 }
throw():在Generator函数体外抛出错误,在Generator函数体内捕获错误,返回自定义的new Errow()
- yield命令:声明内部状态的值(return声明结束返回的值)
遇到yield命令就暂停执行后面的操作,并将其后表达式的值作为返回对象的value
下次调用next()时,再继续往下执行直到遇到下一个yield命令
没有再遇到yield命令就一直运行到Generator函数结束,直到遇到return语句为止并将其后表达式的值作为返回对象的value
Generator函数没有return语句则返回对象的value为undefined
- yield*命令:在一个Generator函数里执行另一个Generator函数(后随具有Iterator接口的数据结构)
- 遍历:通过for-of自动调用next()
- 作为对象属性
全写:const obj = {
method: function*() {
} }
简写:const obj = {
* method() {
} }
- 上下文:执行产生的上下文环境一旦遇到yield命令就会暂时退出堆栈(但并不消失),所有变量和对象会冻结在当前状态,等到对它执行next()时,这个上下文环境又会重新加入调用栈,冻结的变量和对象恢复执行
方法异同:
相同点
next()、throw()、return()本质上是同一件事,作用都是让函数恢复执行且使用不同的语句替换yield命令
不同点
- next():将yield命令替换成一个值 return():
- 将yield命令替换成一个return语句
- throw():将yield命令替换成一个throw语句
应用场景
异步操作同步化表达
控制流管理
为对象部署Iterator接口:把Generator函数赋值给对象的Symbol.iterator,从而使该对象具有Iterator接口
作为具有Iterator接口的数据结构
重点难点:
每次调用next(),指针就从函数头部或上次停下的位置开始执行,直到遇到下一个yield命令或return语句为止
函数内部可不用yield命令,但会变成单纯的暂缓执行函数(还是需要next()触发)
yield命令是暂停执行的标记,next()是恢复执行的操作
yield命令用在另一个表达式中必须放在圆括号里
yield命令用作函数参数或放在赋值表达式的右边,可不加圆括号
yield命令本身没有返回值,可认为是返回undefined
yield命令表达式为惰性求值,等next()执行到此才求值
函数调用后生成遍历器对象,此对象的Symbol.iterator是此对象本身
在函数运行的不同阶段,通过next()从外部向内部注入不同的值,从而调整函数行为
首个next()用来启动遍历器对象,后续才可传递参数
想首次调用next()时就能输入值,可在函数外面再包一层
一旦next()返回对象的done为true,for-of遍历会中止且不包含该返回对象
函数内部部署try-finally且正在执行try,那么return()会导致立刻进入finally,执行完finally以后整个函数才会结束
函数内部没有部署try-catch,throw()抛错将被外部try-catch捕获
throw()抛错要被内部捕获,前提是必须至少执行过一次next()
throw()被捕获以后,会附带执行下一条yield命令
函数还未开始执行,这时throw()抛错只可能抛出在函数外部
首次next()可传值