Generatory

Frontend SELF PL
Poziom 45 , Lekcja 1
Dostępny

2.1 Składnia generatorów

Generatory w JavaScript to specjalne funkcje, które pozwalają zarządzać wykonaniem kodu. Mogą one wstrzymywać swoje wykonanie i wznawiać je później, co czyni je potężnym narzędziem do pracy z kodem asynchronicznym, iteratorami i innymi skomplikowanymi zadaniami.

Generatory definiuje się za pomocą funkcji function* (zauważ gwiazdkę). Wewnątrz generatora używamy operatora yield do wstrzymania wykonania i zwrócenia wartości.

Definicja generatora:

JavaScript
    
      function* generatorFunction() {
        yield 1;
        yield 2;
        yield 3;
      }
    
  

Tworzenie obiektu generatora

Wywołanie generatora nie wykonuje jego ciała od razu. Zamiast tego zwraca on obiekt generatora, który można wykorzystać do iteracji po wartościach:

JavaScript
    
      const gen = generatorFunction();
    
  

2.2 Użycie generatorów

Metoda next()

Metoda next() służy do wznawiania wykonania generatora do następnego operatora yield. Zwraca obiekt z dwoma właściwościami:

  • value: wartość zwrócona przez operator yield
  • done: wartość logiczna wskazująca, czy generator zakończył działanie (true) czy nie (false)

Przykład użycia metody next():

JavaScript
    
      function* generatorFunction() {
        yield 1;
        yield 2;
        yield 3;
      }

      const gen = generatorFunction();

      console.log(gen.next()); // { value: 1, done: false }
      console.log(gen.next()); // { value: 2, done: false }
      console.log(gen.next()); // { value: 3, done: false }
      console.log(gen.next()); // { value: undefined, done: true }
    
  

Iteracja po generatorze

Generatory mogą być używane z pętlą for...of do iteracji po wartościach.

Przykład iteracji po generatorze:

JavaScript
    
      function* generatorFunction() {
        yield 1;
        yield 2;
        yield 3;
      }

      const gen = generatorFunction();

      for (const value of gen) {
        console.log(value);
      }

      // Wypisze: 1
      // Wypisze: 2
      // Wypisze: 3
    
  

Przykład zwracania wartości

Generatory mogą zwracać wartość za pomocą operatora return:

JavaScript
    
      function* generatorFunction() {
        yield 1;
        yield 2;
        return 3;
        yield 4; // Ten yield nigdy nie zostanie wykonany
      }

      const gen = generatorFunction();

      console.log(gen.next()); // { value: 1, done: false }
      console.log(gen.next()); // { value: 2, done: false }
      console.log(gen.next()); // { value: 3, done: true }
      console.log(gen.next()); // { value: undefined, done: true }
    
  

2.3 Skomplikowane użycie generatorów

Interakcja z generatorem

Metoda next() może przyjmować argument, który jest przekazywany do generatora i może być wykorzystany wewnątrz niego.

Przykład przekazywania wartości do generatora:

JavaScript
    
      function* generatorFunction() {
        const value1 = yield 1;
        const value2 = yield value1 + 2;
        yield value2 + 3;
      }

      const gen = generatorFunction();

      console.log(gen.next()); // { value: 1, done: false }
      console.log(gen.next(10)); // { value: 12, done: false }
      console.log(gen.next(20)); // { value: 23, done: false }
      console.log(gen.next()); // { value: undefined, done: true }
    
  

Obsługa błędów

Generatory pozwalają na obsługę błędów przy użyciu bloku try...catch.

Przykład obsługi błędów:

JavaScript
    
      function* generatorFunction() {
        try {
          yield 1;
          yield 2;
        } catch (error) {
          console.log('Wykryty błąd:', error);
        }
      }

      const gen = generatorFunction();

      console.log(gen.next()); // { value: 1, done: false }
      console.log(gen.throw(new Error('Coś poszło nie tak'))); // Wykryty błąd: Error: Coś poszło nie tak

      // { value: undefined, done: true }
    
  

Przykład generatora do tworzenia nieskończonej sekwencji

Generatory mogą być używane do tworzenia nieskończonych sekwencji wartości:

JavaScript
    
      function* infiniteSequence() {
        let i = 0;
        while (true) {
          yield i++;
        }
      }

      const gen = infiniteSequence();

      console.log(gen.next().value); // 0
      console.log(gen.next().value); // 1
      console.log(gen.next().value); // 2

      // i tak dalej
    
  

2.4 Przykłady praktycznego zastosowania

Przykład 1: Generator do iteracji po obiekcie

JavaScript
    
      function* objectEntries(obj) {
        const keys = Object.keys(obj);
        for (const key of keys) {
          yield [key, obj[key]];
        }
      }

      const obj = { a: 1, b: 2, c: 3 };
      const gen = objectEntries(obj);

      for (const [key, value] of gen) {
        console.log(`${key}: ${value}`);
      }

      // Wypisze:
      // a: 1
      // b: 2
      // c: 3
    
  

Przykład 2: Generator do implementacji prostego iteratora

JavaScript
    
      const myIterable = {
        *[Symbol.iterator]() {
          yield 1;
          yield 2;
          yield 3;
        }
      };

      for (const value of myIterable) {
        console.log(value);
      }

      // Wypisze: 1
      // Wypisze: 2
      // Wypisze: 3
    
  

Generatory w JavaScript to potężne narzędzie do zarządzania wykonaniem kodu, tworzenia iteratorów i pracy z operacjami asynchronicznymi. Zrozumienie składni i użycia generatorów pomaga tworzyć bardziej elastyczny i czytelny kod, zwłaszcza przy pracy z sekwencjami danych i zadaniami asynchronicznymi.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION