que-son-las-funciones-generadoras-en-javascript

Qué son las funciones generadoras en JavaScript

En JavaScript una función generadora es un tipo especial de función que puede pausar su ejecución y luego reanudarla en un momento posterior.

Las funciones generadoras son útiles cuando necesitamos trabajar con una gran cantidad de datos o con secuencias grandes, ya que solo calculan los valores a medida que los solicitamos (en lugar de calcular todos los valores de una vez).

Sintaxis básica de las funciones generadoras

  1. Las funciones generadoras se definen utilizando la sintaxis function* (el asterísco indica que la función es una generadora).

  2. Por otro lado, dentro de la función vamos a usar la palabra clave yield (que pausa la ejecución y devolver un valor)

Funcionamiento de yield

  • Cada vez que se encuentra con un yield, la función devuelve el resultado y se suspende en ese punto.
  • Cuando se llama a next() de nuevo, la función generadora continúa ejecutándose justo después del yield que la suspendió.
  • Se ejecutará hasta que encuentre otro yield o termine la ejecución.

El resultado devuelto por yield es un objeto con las propiedades value (el valor generado) y done (un booleano que indica si la secuencia ha terminado).

Ejemplo básico

Vamos a verlo con un ejemplo. En primer lugar, vamos definir una función generadora muy sencilla, que devuelva una secuencia 1, 2 y 3.

function* generadorEjemplo() {
  yield 1; // Pausa aquí y devuelve 1
  yield 2; // Pausa aquí y devuelve 2
  yield 3; // Pausa aquí y devuelve 3
}

En este ejemplo,

  • La función miGeneradora genera tres valores secuenciales: 1, 2 y 3.
  • Cada yield devolverá un valor
  • La ejecución quedará suspendida, hasta que se la vuelva a invocar.

Ahora vamos a ver como podemos utilizar nuestra función generadora. Para ello, simplemente tenemos que invocar a su método next() para solicitarle el siguiente valor.

const generador = generadorEjemplo();

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

En este ejemplo,

  • La función next() se llama repetidamente para obtener el siguiente valor.
  • El resultado obtenido contiene value y done

Funciones generadoras e iteradores

La relación entre funciones generadoras e iteradores es muy estrecha (de hecho, están diseñados para trabajar juntas).

Un iterador es un objeto que debe tener un método next(), que devuelva un objeto con las propiedades value y done.

Como hemos visto, este es exactamente el comportamiento de las funciones generadores cuando usamos yield.

Es decir, que cualquier función generadora es también un iterador. De hecho, podemos usarlas en un bucle for...of

function* colores() {
  yield 'rojo';
  yield 'verde';
  yield 'azul';
}

for (const color of colores()) {
  console.log(color); // 'rojo', 'verde', 'azul'
}

En este ejemplo,

  • El bucle for...of se encarga de llamar automáticamente a next() en el generador y manejar el valor de retorno de cada iteración.
  • Cuando la función generadora termina de producir valores, el bucle for...of termina automáticamente.

Ejemplos prácticos