Funkcje Generatora w TypeScript
Ten artykuł wyjaśnia funkcje generatora w TypeScript.
Możesz nauczyć się wszystkiego, począwszy od podstaw korzystania z funkcji generatorowych, aż po zaawansowane przykłady połączone z przetwarzaniem asynchronicznym, wraz z fragmentami kodu.
YouTube Video
Funkcje Generatora
Funkcje generatora w TypeScript oferują podobną funkcjonalność jak funkcje generatora w JavaScript. Funkcje generatora definiuje się za pomocą function* (deklaracja funkcji z gwiazdką) i są to specjalne funkcje, które mogą wstrzymywać i wznawiać wykonanie, w przeciwieństwie do zwykłych funkcji.
Kiedy wywoływana jest funkcja generatora, zwracany jest iterator, który generuje wartości jedna po drugiej za pomocą iteratora, a wykonanie można wstrzymać za pomocą słowa kluczowego yield lub przesyłać wartości z zewnątrz.
Podstawowa składnia funkcji generatora
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)
- Zdefiniuj funkcję generatora za pomocą
function* myGenerator(). - Słowo kluczowe
yieldwstrzymuje wykonanie funkcji, zwracając jednocześnie wartość. - Za każdym razem, gdy wywoływana jest metoda
next(), wykonanie funkcji generatora jest wznawiane i przechodzi do następnegoyield.
next() zwraca obiekt zawierający następną wartość oraz właściwość done. Kiedy done jest równe true, oznacza to, że wszystkie wartości zostały wygenerowane i przetwarzanie generatora zostało zakończone.
Zastosowania funkcji generatora
Korzystanie z funkcji generatora umożliwia łatwe przedstawienie przetwarzania sekwencyjnego. W poniższym przykładzie tworzymy funkcję generatora, która generuje sekwencję liczb.
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
- W tym przykładzie
sequenceGeneratorgeneruje nieskończenie rosnącą sekwencję liczb. Użyjyield, aby zwrócić wartości na każdym kroku, i generuj kolejną wartość w kolejnych wywołaniach.
Przekazywanie wartości do next
Metoda next() może otrzymać wartość, która może zostać przesłana do funkcji generatora.
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
- W tym przykładzie
next(5)inext(10)przesyłają swoje wartości do funkcji generatora, ayield num1 + num2zwraca ich sumę.
return i throw
return(value)może zakończyć generator i zwrócić określoną wartość.throw(error)może wyrzucić wyjątek wewnątrz generatora, stosowany do obsługi wyjątków w obrębie generatora.
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!
- W tym przykładzie metoda
throwjest używana do wygenerowania błędu wewnątrz generatora, a ten błąd jest przechwytywany w obrębie generatora.
Definicja typów w TypeScript
Definicję typu funkcji generatora można określić w następującym formacie.
1// Generator<YieldType, ReturnType, NextType>
2function* myGenerator(): Generator<number, void, unknown> {
3 yield 1;
4 yield 2;
5 yield 3;
6}- Określasz typy w formie
Generator<YieldType, ReturnType, NextType>.YieldTypeto typ wartości zwracanej przezyield.ReturnTypeto typ wartości zwracanej przezreturn.NextTypeto typ wartości przekazywanej donext().
W poniższym przykładzie określono konkretne typy, aby bezpiecznie korzystać z generatora z zastosowaniem typów.
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)
Generatory i przetwarzanie asynchroniczne
Generatory mogą być również wykorzystywane do przetwarzania asynchronicznego. Na przykład możesz użyć yield, aby poczekać na wyniki operacji asynchronicznych, jednocześnie kontynuując przetwarzanie sekwencyjne. Jednak w TypeScript lub JavaScript częściej stosuje się 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}Chociaż możesz przetwarzać operacje asynchroniczne sekwencyjnie za pomocą generatorów, nie są one powszechnie używane w przetwarzaniu asynchronicznym, ponieważ Promisy i async/await są bardziej wygodne.
Podsumowanie
- Funkcje generatorowe to specjalne funkcje zdefiniowane za pomocą
function*, które mogą zwracać wartości za pomocąyield, jednocześnie wstrzymując wykonywanie funkcji. - Użyj
next(), aby wznowić generator i otrzymać wartości. Dodatkowo możesz przesyłać wartości do generatora, używającnext(value). - Możesz używać
return()ithrow(), aby zakończyć funkcje generatorowe lub obsłużyć błędy. - Podczas korzystania z generatorów w TypeScript możesz używać definicji typów, aby pisać kod bezpieczny typowo.
Generatory to potężne narzędzia, które pozwalają elastycznie kontrolować iterację.
Możesz śledzić ten artykuł, korzystając z Visual Studio Code na naszym kanale YouTube. Proszę również sprawdzić nasz kanał YouTube.