006. Generators

En el capítulo anterior veíamos el concepto de los tipos de datos que son iterables, y de una interface que los elementos iterables tienen, denominada iterador.

En este capítulo vamos a ver una sintaxis más sencilla para generar iteradores, que se conoce como generators o generadores, y es una función que permite trabajar de una manera más amigable con la interface de los iteradores en un elemento iterable.

Veamos un ejm.

Ejm

function* iterable() {
   // El asterisco le indica a Javascript que es un generador
   yield "Hola";
   console.log("Hola consola");
   yield "hola 2";
   console.log("Mas instrucciones de código");
   yield "Hola 3";
   yield "Hola 4";
}

let iterador = iterable();
console.log(iterador.next());
// Imprimirá el primer "Hola" del primer yield
console.log(iterador.next());
// Imprime "Hola consola" y "Hola 2" del segundo yield

El asterisco (*) le indica a Javascript que es un generador. Utilizamos la palabra reservada yield, que es como un return, que le va a indicar a la función que cuando detecte que la han mandado a llamar con el método next() del iterador, aquí mando el primer valor, y dejamos el cursor en el código interno de la función. Cuando se vuelve a ejecutar un segundo método next() fuera de esta función, iría a buscar el siguiente yield. Si no encontramos un yield, significa que ha acabado con los valores de la función iterable, y el método next() nos daría en su propiedad done el valor true.

Nota: Hasta cierto punto, los generadores nos permiten manejar comportamiento asíncrono.

Un generador lo que transforma es el código de una función en iterable.

El ejm de arriba lo podemos transformar de la siguiente manera.

Ejm

function* iterable() {
   // El asterisco le indica a Javascript que es un generador
   yield "Hola";
   console.log("Hola consola");
   yield "hola 2";
   console.log("Mas instrucciones de código");
   yield "Hola 3";
   yield "Hola 4";
}

let iterador = iterable();

// Bucle forof para ir leyendo todos los elementos
for (let y of iterador) {
console.log(y);
}

Recolectar todos los yields en un Array

Lo haríamos con la siguiente sintaxis después de la última linea de código incluida en nuestro ejm.

Ejm

let arr = [...iterable()];
console.log(arr);
// Devuelve un Array con todos nuestros yields

Ejm completo

Veamos un ejm para entender mejor el uso de los generadores.

Ejm

function cuadrado(value) {
  setTimeout(() => {
    return console.log({value, resultado: value * value})
  }, 1000);
}

function* generador() {
  console.log("Inicia Generator");
  yield cuadrado(0);
  yield cuadrado(1);
  yield cuadrado(2);
  yield cuadrado(3);
  yield cuadrado(4);
  yield cuadrado(5);
  console.log("Termina Generator");
}

let gen = generador();
  for (let y of gen) {
  console.log(y);
}

En este ejm estamos teniendo una asincronía con un comportamiento no bloqueante.

Scroll al inicio