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>
    • YieldType 是由 yield 回傳值的類型。
    • ReturnType 是由 return 回傳值的類型。
    • 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