TypeScript 中的生成器函数

TypeScript 中的生成器函数

本文解释了 TypeScript 中的生成器函数。

您可以学习从生成器函数的使用基础到与异步处理结合的高级示例,以及相关的代码示例。

YouTube Video

生成器函数

TypeScript 中的生成器函数提供了与 JavaScript 生成器函数类似的功能。生成器函数使用 function*(带星号的函数声明)定义,是一种特殊的函数,可以暂停和恢复执行,而不像普通函数那样直接运行到底。

调用生成器函数时,会返回一个 迭代器,该迭代器通过 yield 关键字生成值并暂停执行,还可以从外部传递值进入生成器。

生成器函数的基本语法

 1function* myGenerator(): Generator<number, void, unknown> {
 2    yield 1;
 3    yield 2;
 4    yield 3;
 5}
 6
 7const gen = myGenerator();
 8
 9console.log(gen.next().value); // 1
10console.log(gen.next().value); // 2
11console.log(gen.next().value); // 3
12console.log(gen.next().done);  // true (Iteration finished)
  • 使用 function* myGenerator() 定义一个生成器函数。
  • yield 关键字在返回一个值的同时暂停函数的执行。
  • 每次调用 next() 方法时,生成器函数的执行都会恢复并继续运行至下一个 yield

next() 方法返回一个包含下一个值和 done 属性的对象。当 donetrue 时,表示所有值已经生成,生成器处理已完成。

生成器函数的应用

使用生成器函数可以轻松地表示顺序处理。在以下示例中,我们创建了一个生成器函数来生成一系列的数字。

 1function* sequenceGenerator(start: number = 0, step: number = 1) {
 2    let current = start;
 3    while (true) {
 4        yield current;
 5        current += step;
 6    }
 7}
 8
 9const seq = sequenceGenerator(1, 2);
10
11console.log(seq.next().value); // 1
12console.log(seq.next().value); // 3
13console.log(seq.next().value); // 5
  • 在此示例中,sequenceGenerator 生成了一个无限递增的数字序列。使用 yield 在每一步返回一个值,并在后续调用时生成下一个值。

next 传递值

next() 方法可以接收一个值,该值可以传递到生成器函数中。

 1function* adder() {
 2    const num1 = yield;
 3    const num2 = yield;
 4    yield num1 + num2;
 5}
 6
 7const addGen = adder();
 8addGen.next();          // Initialization
 9addGen.next(5);         // Set 5 to num1
10const result = addGen.next(10).value; // Set 10 to num2 and get result
11console.log(result);    // 15
  • 在此示例中,next(5)next(10) 将各自的值传递到生成器函数中,而 yield num1 + num2 返回它们的和。

returnthrow

  • return(value) 可以终止生成器并返回指定的值。
  • throw(error) 可以在生成器内部抛出异常,用于在生成器中处理异常。
 1function* testGenerator() {
 2    try {
 3        yield 1;
 4        yield 2;
 5    } catch (e) {
 6        console.error("Error caught:", e);
 7    }
 8}
 9
10const gen = testGenerator();
11console.log(gen.next().value); // 1
12gen.throw(new Error("An error occurred!")); // Error caught: An error occurred!
  • 在此示例中,使用 throw 方法在生成器内部生成一个错误,并在生成器中捕获该错误。

TypeScript中的类型定义

生成器函数的类型定义可以用以下格式指定。

1// Generator<YieldType, ReturnType, NextType>
2function* myGenerator(): Generator<number, void, unknown> {
3    yield 1;
4    yield 2;
5    yield 3;
6}
  • 您可以使用Generator<YieldType, ReturnType, NextType>的形式指定类型。
    • YieldTypeyield 返回值的类型。
    • ReturnTypereturn 返回值的类型。
    • NextType 是传递给 next() 的值的类型。

在以下示例中,指定了特定类型以便安全地使用带有类型的生成器。

 1function* numberGenerator(): Generator<number, void, number> {
 2    const num1 = yield 1;
 3    const num2 = yield num1 + 2;
 4    yield num2 + 3;
 5}
 6
 7const gen = numberGenerator();
 8
 9console.log(gen.next().value);   // 1
10console.log(gen.next(10).value); // 12 (10 + 2)
11console.log(gen.next(20).value); // 23 (20 + 3)

生成器与异步处理

生成器也可以用于异步处理。例如,您可以使用yield等待异步操作的结果,同时继续进行顺序处理。然而,在TypeScript或JavaScript中,async/await更为常用。

1function* asyncTask() {
2    const result1 = yield fetch("https://codesparklab.com/json/example1.json");
3    console.log(result1);
4
5    const result2 = yield fetch("https://codesparklab.com/json/example2.json");
6    console.log(result2);
7}

因此,尽管可以使用生成器顺序处理异步操作,但由于Promises和async/await更为方便,它们并不常被用于异步处理。

总结

  • 生成器函数是使用function*定义的特殊函数,它可以通过yield返回值,同时暂停函数的执行。
  • 使用**next()**恢复生成器并接收值。此外,您可以使用next(value)将值发送到生成器中。
  • 您可以使用**return()throw()**终止生成器函数或处理错误。
  • 在TypeScript中使用生成器时,您可以利用类型定义编写类型安全的代码。

生成器是强大的工具,允许您灵活地控制迭代。

您可以在我们的YouTube频道上使用Visual Studio Code跟随上述文章进行学习。 请也查看我们的YouTube频道。

YouTube Video