深入理解TypeScript
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.12 generators

function*是一个用来创建generators函数的语法。调用一个generators函数将会返回一个generators对象。而这个generators对象只是遵循了迭代器的接口(即next、return和throw函数)。

设计generators的关键目的有两个。

1.惰性迭代器

generators函数可以用来创建惰性迭代器,例如,下面的函数根据需要会返回无限的整数列表。

当然,如果迭代确实结束了,你将会获得{done:true}结果,如下所示。

2.外部控制执行

这是generators的一个真正令人兴奋的特性。它实际上可以让一个函数暂停执行,并将继续执行的权力交给调用者。

一个generators函数并不会在调用时执行,它只是创建一个generators对象,示例如下。

如果你执行上面的代码,会得到以下输出。

● generators函数只有当你在generators对象上调用next时才开始执行。

● 一旦遇到yield语句,generators函数将会暂停执行。

● 当next被调用时,generators函数会恢复执行。

因此,实际上generators函数的执行是由generators对象控制的。

这里,我们使用generators的一种主要方式是通过generators返回迭代的值。在JavaScript中,generators的一项非常强大的功能是允许双向通信(带有警告)。

● 你可以通过iterator.next(value.ToInject)控制yield表达式的结果。

● 当yield表达式使用iterator.throw(error)时,你可以抛出一个异常。

下面的示例演示了iterator.next(valueToInject)。

因为yield返回了传递给迭代器next函数的参数,而所有的迭代器next函数都接受任意类型的参数,因此,TypeScript总是会把any分配给yield操作符的返回值(如上文中的bar)。

你可以将所得结果的类型强制转化为你期望的类型,并确保仅将该类型的值传递给下一个。例如,基于框架你可以写一个额外的类型增强层,然后使用它来调用next函数。如果强类型对你来说很重要,那么你应该完全避免双向通信的情况,并且高度依赖它所提供的包(如redux-saga)。

下面的示例演示了iterator.throw(error)。

总结如下。

● yield允许一个generators函数暂停执行,并且将恢复执行的权力交给外部系统。

● 外部系统可以将值推入generators函数体。

● 外部系统可以将一个异常抛入generators函数体。

讲这些有什么用呢?你可以在下一节内容中找到答案。