TypeScript入门教程 之 生成器函数
生成器函数
function *
是用于创建生成器函数的语法。调用generator函数将返回一个generator对象。发电机对象如下刚刚所述迭代器接口(即next
,return
和throw
函数)。
生成器功能背后有两个主要动机:
延迟迭代器
生成器函数可用于创建延迟迭代器,例如,以下函数根据需要返回无限的整数列表:
function* infiniteSequence() {
var i = 0;
while(true) {
yield i++;
}
}
var iterator = infiniteSequence();
while (true) {
console.log(iterator.next()); // { value: xxxx, done: false } forever and ever
}
当然,如果迭代器确实结束了,您将得到{ done: true }
如下所示的结果:
function* idMaker(){
let index = 0;
while(index < 3)
yield index++;
}
let gen = idMaker();
console.log(gen.next()); // { value: 0, done: false }
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { done: true }
外部控制执行
这是发电机真正令人兴奋的部分。它本质上允许函数暂停其执行,并将其余函数执行的控制权(命运)传递给调用者。
生成器函数在调用时不会执行。它只是创建一个生成器对象。考虑以下示例以及示例执行:
function* generator(){
console.log('Execution started');
yield 0;
console.log('Execution resumed');
yield 1;
console.log('Execution resumed');
}
var iterator = generator();
console.log('Starting iteration'); // This will execute before anything in the generator function body executes
console.log(iterator.next()); // { value: 0, done: false }
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
如果运行此命令,将得到以下输出:
$ node outside.js
Starting iteration
Execution started
{ value: 0, done: false }
Execution resumed
{ value: 1, done: false }
Execution resumed
{ value: undefined, done: true }
- 该函数仅
next
在生成器对象上被调用一次才开始执行。 - 一旦遇到语句,该函数就会暂停
yield
。 - 该函数在被调用时恢复
next
。
因此,基本上生成器功能的执行可由生成器对象控制。
我们使用生成器进行通信主要是一种方法,其中生成器返回迭代器的值。JavaScript生成器的一个极其强大的功能是它们允许双向通信(带有警告)。
- 您可以使用以下方法控制
yield
表达式的结果值iterator.next(valueToInject)
- 您可以
yield
使用以下方式在表达式的位置抛出异常iterator.throw(error)
以下示例演示iterator.next(valueToInject)
:
function* generator() {
const bar = yield 'foo'; // bar may be *any* type
console.log(bar); // bar!
}
const iterator = generator();
// Start execution till we get first yield value
const foo = iterator.next();
console.log(foo.value); // foo
// Resume execution injecting bar
const nextThing = iterator.next('bar');
由于yield
返回传递给迭代next
器next
函数的参数,并且所有迭代器的函数都接受任何类型的参数,因此TypeScript将始终将any
类型分配给yield
运算符的结果(bar
如上)。
您可以自行将结果强制为所需的类型,并确保仅将该类型的值传递给下一个类型(例如,通过搭建一个额外的要求
next
您的类型强制层)。如果强类型对于您可能希望完全避免双向通信,以及完全依赖它的软件包(例如redux-saga)。
以下示例演示iterator.throw(error)
:
function* generator() {
try {
yield 'foo';
}
catch(err) {
console.log(err.message); // bar!
}
}
var iterator = generator();
// Start execution till we get first yield value
var foo = iterator.next();
console.log(foo.value); // foo
// Resume execution throwing an exception 'bar'
var nextThing = iterator.throw(new Error('bar'));
因此,这里是摘要:
yield
允许生成器功能暂停其通信并将控制权传递给外部系统- 外部系统可以将值推入生成器功能主体
- 外部系统可以在生成器函数体中引发异常
这有什么用?跳转到下一部分异步/等待并查找。
翻译来源:https://gitee.com/yunwisdoms/typescript-book/blob/master/docs/generators.md