Генераторные функции в 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. Когда done равно true, это означает, что все значения сгенерированы и выполнение генераторной функции завершено.

Применение генераторных функций

Использование генераторных функций позволяет удобно представлять последовательную обработку. В следующем примере мы создаем генераторную функцию, которая генерирует последовательность чисел.

 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 возвращает их сумму.

return и throw

  • 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 вы можете применять определения типов для написания безопасного кода.

Генераторы — это мощные инструменты, позволяющие гибко управлять итерацией.

Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.

YouTube Video