Funciones generadoras en JavaScript: ¿Que son y como hacer?
Las funciones asíncronas en JavaScript son una herramienta clave para manejar tareas que requieren tiempo, como solicitudes a servidores o temporizadores. Con características que simplifican el manejo de promesas, te permiten escribir código más claro y eficiente. En este artículo descubrirás qué son, cómo usarlas, ejemplos prácticos y para qué sirven en el desarrollo moderno.

Índice
1. ¿Que son las funciones generadoras en JavaScript?
Imagina una función que, en lugar de ejecutar todo su código de una sola vez, pueda pausarse y reanudarse en cualquier momento. Esto es precisamente lo que hacen las funciones generadoras.
Son un tipo especial de función que puede pausar su ejecución, guardar su estado interno y reanudar su ejecución posteriormente desde donde se quedó.
Estas funciones se utilizan para producir una secuencia de valores bajo demanda, en lugar de generar todos los valores de una vez, como lo haría una función convencional.
¿CÓMO FUNCIONAN?
- Declaración:
- Se declaran con la palabra clave
function*.
- Se declaran con la palabra clave
- Pausar y reanudar:
- Utilizan la palabra clave
yieldpara pausar la ejecución y devolver un valor. Cuando se vuelve a llamar a la función, se reanuda desde el punto donde se quedó.
- Utilizan la palabra clave
- Objeto generador:
- Al llamar a una función generadora, no se ejecuta el código inmediatamente, sino que se devuelve un objeto generador. Este objeto tiene un método
next()(también existen otros que ya explicaremos) que se utiliza para avanzar la ejecución de la función.
- Al llamar a una función generadora, no se ejecuta el código inmediatamente, sino que se devuelve un objeto generador. Este objeto tiene un método
1.1. Ejemplo de una función generadora con JS:
// 1- Definición de la función generadora
function* simpleGenerador() {
yield 1; // Pausa aquí y devuelve 1
yield 2; // Pausa aquí y devuelve 2
yield 3; // Pausa aquí y devuelve 3
}
// 2- Llamada a la función generadora
const gen = simpleGenerador();
// 3- Usamos los métodos next()
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 }Lenguaje del código: JavaScript (javascript)
¿Que hace esta función generadora?
- Definición de la función generadora:
- Define una función generadora llamada
simpleGenerador(se identifica gracias afunction*) . - Contiene tres declaraciones
yield, que generan valores secuenciales (1, 2, 3). - Los valores de estos
yieldse ejecutan connext(), y se pausa en el próximoyield.- Cada vez que la ejecución se reanuda con
next(), la función genera un valor y pausa en el siguienteyield.
- Cada vez que la ejecución se reanuda con
- Define una función generadora llamada
- Llamada a la función generadora:
const gen = simpleGenerador();- Aquí, llamamos la función generadora
simpleGenerador()pero no la ejecutamos inmediatamente. - En su lugar, devolvemos un objeto generador (
gen) que tiene métodos comonext()para controlar la ejecución. - Posteriormente, con cada llamada a la función usando
next()iremos ejecutando el código de cadayieldprogresivamente.
- Aquí, llamamos la función generadora
- Explicación de cada llamada a
gen.next()- PRIMERA LLAMADA:
console.log(gen.next()); // { value: 1, done: false }- La función comienza a ejecutarse desde el inicio y se detiene en el primer
yield. - Devuelve
{ value: 1, done: false }:value: El valor generado poryield 1.done:falseporque el generador no ha terminado (hay másyieldpendientes).
- La función comienza a ejecutarse desde el inicio y se detiene en el primer
- SEGUNDA LLAMADA:
console.log(gen.next()); // { value: 2, done: false }- La ejecución se reanuda desde donde se detuvo (después de
yield 1) y continúa hasta el siguienteyield. - Devuelve
{ value: 2, done: false }:value: El valor generado poryield 2.done:falseporque aún hay másyieldpendientes.
- La ejecución se reanuda desde donde se detuvo (después de
- TERCERA LLAMADA:
console.log(gen.next()); // { value: 3, done: false }- La ejecución continúa desde donde se detuvo (después de
yield 2) hasta el siguienteyield. - Devuelve
{ value: 3, done: false }:value: El valor generado poryield 3.done:falseporque aún no ha terminado.
- La ejecución continúa desde donde se detuvo (después de
- CUARTA LLAMADA (Sin Más
yield)console.log(gen.next()); // { value: undefined, done: true }- Ahora la función generadora no tiene más
yieldy ha terminado de ejecutarse. - Devuelve
{ value: undefined, done: true }:value:undefinedporque no se generó ningún valor.done:trueporque el generador ya terminó.
- Ahora la función generadora no tiene más
- PRIMERA LLAMADA:
NOTA!!!! Si te animas y deseas ver el resultado de este ejemplo y de todos los que iremos proporcionando directamente desde tu PC, te invito a seguir estos pasos.
- Primero, revisa el punto 5 del siguiente artículo sobre como usar e instalar VSCode (este es el editor de código mas usado), donde encontrarás los pasos para crear la estructura necesaria para visualizar una página desde tu navegador predeterminado.
- Si entendiste correctamente este paso anterior, sabrás donde colocar el código
scriptque te acabamos de proporcionar (arriba). Ahora, puedes visualizar el resultado, para ello puedes hacer lo siguiente:- Una vez abierta y visualizada la página, abre la consola del navegador presionando la tecla F12.
- Ahora, dirígete a la pestaña que dice
Console, y desde aquí podrás ver el resultado del script que hayamos introducido anteriormente.
- No te preocupes, estos pasos son más simples de lo que parecen!!!! Entonces… cada vez que dejemos un código de ejemplo como éste, puedes seguir estos pasos y ver los resultados por ti mismo. ¡Ojalá te animes!!!!
2. ¿Cómo se hace una función generadora con JS?
Para entender mejor como funciona y como hacer estas funciones, primero veremos la sintaxis para crear la función generadora, y después la sintaxis para llamar y hace uso de dicha función.
2.1. Sintaxis para crear la función generadora:
function* nombre([parámetros]) {
// Cuerpo de la función generadora
yield valor;
// Más lógica o valores con yield
return valorFinal; // (Opcional)
}Lenguaje del código: JavaScript (javascript)
Elementos de la sintaxis y su explicación:
function*(Definición de Generador)- La palabra clave
functionindica que estás declarando una función. - El asterisco (
*):- Es obligatorio para definir una función generadora.
- Lo puedes colocar junto al nombre de la función o con un espacio intermedio. Ambos son válidos:
- Ejemplo:
function* generador() { ... } // Válidofunction *generador() { ... } // Válido
- La palabra clave
nombre(Nombre de la Función Generadora)- Igual que las funciones regulares, una función generadora puede tener un nombre opcional:
- Si tiene nombre, es útil para llamarla o referenciarla más adelante.
- Si es anónima, puede usarse como función asignada a una variable.
- Igual que las funciones regulares, una función generadora puede tener un nombre opcional:
- Parámetros (Opcionales):
- Igual que en las funciones regulares, puedes definir parámetros para pasar valores al generador cuando lo invoques:
- Cuerpo de la función generadora
- Aquí escribes el bloque de código que define el comportamiento de tu generador .
- Incluye lógica, cálculos, o cualquier otro flujo que quieras controlar con
yield.
yield(Producción de Valores)- SIGNIFICADO:
- Es una palabra clave que pausa la ejecución de la función generadora y devuelve un valor al invocador (quien llama a
next()).
- Es una palabra clave que pausa la ejecución de la función generadora y devuelve un valor al invocador (quien llama a
- FUNCIONAMIENTO:
- Cuando la ejecución se reanuda con
next(), la función continúa desde el punto donde quedó (después del últimoyield).
- Cuando la ejecución se reanuda con
- SIGNIFICADO:
return(Opcional)- Puedes usar la palabra clave
returnpara devolver un valor final desde el generador, marcando el final del ciclo (explicamos en punto 4)
- Puedes usar la palabra clave
2.2. Sintaxis para llamar a la función generadora:
// Creando un Objeto Generador
const generador = nombreGenerador();
// Métodos del Objeto Generador
generador.next(); // Avanza al próximo `yield` y devuelve un objeto { value, done }
generador.return(); // Finaliza la ejecución del generador manualmente
generador.throw(); // Lanza un error dentro del generadorLenguaje del código: PHP (php)
Con esta sintaxis, podemos llamar a la función generadora y ejecutar su código.
Explicación de esta sintaxis:
- Llamando a la función generadora:
const generador = nombreGenerador();- Aquí, llamamos a la función generadora
nombreGenerador(), (almacenándolo en una variable,generadoren este caso) pero no se ejecuta inmediatamente. - Devuelve un objeto generador, que permite controlar la ejecución.
- ¿Qué es un objeto generador?:
- Un objeto generador es como un iterador que puede pausar y reanudar su ejecución. Tiene un método clave llamado
next()que controla la ejecución de la función generadora. Aunque también se puede usar con otros métodos.
- Un objeto generador es como un iterador que puede pausar y reanudar su ejecución. Tiene un método clave llamado
- Aquí, llamamos a la función generadora
- Método
next():generador.next();- Ejecuta el cuerpo del código que hayamos establecido en cada
yield(en la sintaxis del punto 2.1.),- Y recuerda, la ejecución de los siguientes
yieldno continúa hasta que se establezca el siguientegenerador.next();
- Y recuerda, la ejecución de los siguientes
- Devuelve como resultado un objeto con dos propiedades:
value: El valor generado poryield.done:falsesi hay másyieldpendientes,truesi terminó.
- Ejecuta el cuerpo del código que hayamos establecido en cada
- Método
return(valorFinal):generador.return();- Finaliza la ejecución del generador antes de que termine naturalmente.
- Opcionalmente, podemos pasarle un valor de retorno.
- Ejemplo:
function* miGenerador() {
yield 'Paso 1';
yield 'Paso 2';
yield 'Paso 3';
}
const gen = miGenerador();
console.log(gen.next()); // { value: 'Paso 1', done: false }
console.log(gen.return('Fin Manual')); // { value: 'Fin Manual', done: true }
console.log(gen.next()); // { value: undefined, done: true } (ya terminó)Lenguaje del código: JavaScript (javascript)
- Método
throw(error):generador.throw(new Error('Algo salió mal'));- Lanza un error dentro del generador.
- Si el generador tiene manejo de errores (
try...catch), se puede capturar.
CÓDIGO COMPLETO DE LA SINTAXIS:
function* nombre([parámetros]) {
// Cuerpo de la función generadora
yield valor;
// Más lógica o valores con yield
return valorFinal; // (Opcional)
}
// Creando un Objeto Generador
const generador = nombre();
// Métodos del Objeto Generador
generador.next(); // Avanza al próximo `yield` y devuelve un objeto { value, done }
generador.return(); // Finaliza la ejecución del generador manualmente
generador.throw(); // Lanza un error dentro del generadorLenguaje del código: PHP (php)
3. Iteración con generadores en JavaScript
- ¿Qué significa que un generador sea iterable?
- Uso de for…of con generadores
- Diferencia entre for…of y next() manualmente:
- Ejemplo con generador infinito (Uso de break)
- Conclusión
3.1. ¿Qué significa que un generador sea iterable?
🔹 Ser iterable significa que un objeto puede recorrerse elemento por elemento utilizando estructuras como for...of.
🔹 Los generadores son iterables por naturaleza, lo que significa que podemos recorrer sus valores sin necesidad de llamar manualmente a next().
🔹 En lugar de usar next() repetidamente, podemos usar for...of para iterar automáticamente hasta que el generador termine.
3.2. Uso de for...of con generadores
La ventaja de for...of es que simplifica la obtención de valores sin necesidad de manejar manualmente next().
function* contar() {
yield 1;
yield 2;
yield 3;
}
for (const numero of contar()) {
console.log(numero);
}Lenguaje del código: JavaScript (javascript)
📌 Explicación:
- Se define la función generadora
contar(), que devuelve1,2y3conyield. - Usamos
for...of, que itera automáticamente sobre los valores del generador. - En cada iteración,
for...ofllama anext()internamente y obtiene elvalue. - Cuando ya no hay más
yield, el bucle termina.
🔹 Salida en consola:
1
2
3
3.3. Diferencia entre for...of y next() manualmente:
🔹 Usar next() manualmente:
const gen = contar();
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 }Lenguaje del código: JavaScript (javascript)
🔹 Usar for...of simplifica el código:
for (const numero of contar()) {
console.log(numero);
}Lenguaje del código: JavaScript (javascript)
✅ VENTAJA DE for...of: Más limpio, automático y sin necesidad de controlar done.
3.4. Ejemplo con generador infinito (Uso de break)
Si un generador no tiene un fin definido, for...of seguiría ejecutándose indefinidamente. Podemos usar break para detenerlo.
function* numeros() {
let num = 1;
while (true) {
yield num++;
}
}
for (const numero of numeros()) {
if (numero > 5) break; // Detiene la iteración cuando llega a 5
console.log(numero);
}Lenguaje del código: JavaScript (javascript)
🔹 Salida:
1
2
3
4
5
📌 Explicación:
- La función generadora
numeros()genera números infinitamente conwhile (true). for...ofrecorre los valores del generador automáticamente.- Se usa
breakpara detener el bucle cuandonumero > 5, evitando un bucle infinito.
3.5. Conclusión
✅ Los generadores son iterables, lo que significa que se pueden recorrer fácilmente con for...of.
✅ for...of maneja internamente next() y la condición de finalización, haciendo el código más limpio y legible.
✅ Es útil para recorrer secuencias de valores generados dinámicamente sin necesidad de estructuras de datos adicionales.
4. Generadores y return
4.1. ¿Qué pasa al usar return?
Cuando se usa return dentro de un generador, la ejecución se detiene inmediatamente y el generador se marca como done: true.
🔹 Cualquier yield después de return no se ejecutará.
🔹 Si return se usa en medio de la ejecución, se termina el generador antes de llegar a todos los valores posibles.
4.2. ¿Cuál es la diferencia entre return y yield?
🔹 yield pausa la ejecución y permite continuar con next().
🔹 return termina el generador inmediatamente y marca done: true.
EJEMPLO:
function* numeros() {
yield 1;
yield 2;
return 3; // Termina el generador inmediatamente
yield 4; // Nunca se ejecutará
}
const gen = numeros();
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 }Lenguaje del código: JavaScript (javascript)
Explicación:
yield 1;devuelve1y pausa la ejecución.yield 2;devuelve2y pausa la ejecución nuevamente.return 3;devuelve3pero marca el generador como terminado (done: true).yield 4;nunca se ejecuta porque elreturnterminó la función generadora.
Salida en consola:
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: true }
{ value: undefined, done: true }Lenguaje del código: CSS (css)
5. Generadores anidados
- ¿Qué es un generador anidado?
- Ejemplos de un generador anidado con yield*:
- ¿Qué pasa cuando usamos yield*?
5.1. ¿Qué es un generador anidado?
Un generador anidado es un generador que llama a otro generador dentro de sí mismo.
🔹 Se pueden usar múltiples generadores para dividir tareas en partes más pequeñas y organizadas.
🔹 Para delegar la ejecución a otro generador, se usa la sintaxis yield*.
5.2. Ejemplos de un generador anidado con yield*:
function* generadorInterno() {
yield "A";
yield "B";
}
function* generadorExterno() {
yield "Inicio";
yield* generadorInterno(); // Delegación del generador
yield "Fin";
}
const gen = generadorExterno();
console.log(gen.next()); // { value: 'Inicio', done: false }
console.log(gen.next()); // { value: 'A', done: false }
console.log(gen.next()); // { value: 'B', done: false }
console.log(gen.next()); // { value: 'Fin', done: false }
console.log(gen.next()); // { value: undefined, done: true }Lenguaje del código: JavaScript (javascript)
📌 Explicación:
yield "Inicio";devuelve"Inicio"y pausa la ejecución.yield* generadorInterno();llama al generador interno y delega la ejecución en él.yield "A";del generador interno se ejecuta.yield "B";del generador interno se ejecuta.
yield "Fin";devuelve"Fin"después de quegeneradorInternotermina.
🔹 Salida en consola:
{ value: 'Inicio', done: false }
{ value: 'A', done: false }
{ value: 'B', done: false }
{ value: 'Fin', done: false }
{ value: undefined, done: true }Lenguaje del código: CSS (css)
5.3. ¿Qué pasa cuando usamos yield*?
Cuando un generador usa yield* otroGenerador(), todas las iteraciones del generador interno se incorporan al generador principal.
🔹 El generador externo no tiene que manejar cada yield del interno manualmente.
🔹 Todos los valores generados por el generador interno se «fusionan» con el externo.
6. Funciones generadores, asincronía y su uso con promesas.
- Qué es asincronía?
- ¿Qué son las promesas?
- Uso de generadores con promesas
- Beneficios de usar generadores con promesas
- Conclusión
6.1. ¿Qué es asincronía?
Asincronía en JavaScript significa que ciertas operaciones no se ejecutan de inmediato y el código sigue corriendo sin esperar su finalización.
Se usa principalmente cuando trabajamos con tareas que tardan en completarse, como:
- Peticiones a servidores (fetch, API REST).
- Operaciones con bases de datos.
- Temporizadores y animaciones.
6.2. ¿Qué son las promesas?
Una promesa es un objeto que representa un valor que estará disponible en el futuro.
Puede estar en tres estados:
- Pending (Pendiente): Aún no se ha resuelto.
- Fulfilled (Resuelta): Se completó exitosamente.
- Rejected (Rechazada): Ocurrió un error.
6.3. Uso de generadores con promesas
Los generadores pueden manejar promesas de manera estructurada sin usar async/await. Se usa un controlador externo (next()) para manejar la ejecución paso a paso.
Ejemplo:
function* obtenerDatos() {
console.log("Solicitando datos...");
const datos = yield new Promise(resolve => setTimeout(() => resolve("Datos recibidos"), 2000));
console.log(datos);
}
const generador = obtenerDatos();
const promesa = generador.next().value;
promesa.then(resultado => generador.next(resultado));Lenguaje del código: JavaScript (javascript)
📌 Explicación:
console.log("Solicitando datos...");imprime un mensaje.yield new Promise(...)pausa la ejecución del generador hasta que la promesa se resuelve.generador.next().value;obtiene la promesa y la almacena enpromesa.promesa.then(resultado => generador.next(resultado));- Espera que la promesa termine.
- Llama
generador.next(resultado);pasando el valor resuelto ("Datos recibidos").
- Se ejecuta
console.log(datos);dentro del generador con"Datos recibidos".
6.4. Beneficios de usar generadores con promesas
✅ Estructura más clara que las promesas encadenadas (.then()).
✅ Evita callback hell (anidación excesiva de funciones).
✅ Puede ser usado para implementar manejadores de tareas asincrónicas.
6.5. Conclusión
🔹 Asincronía permite que el código no bloquee la ejecución mientras espera respuestas.
🔹 Las promesas representan valores futuros y permiten manejar procesos asincrónicos.
🔹 Los generadores pueden manejar promesas, pausando la ejecución hasta que los datos sean recibidos.
7. ¿Para que sirven las funciones generadoras en JavaScript?
- Iteradores personalizados:
- Generación de secuencias infinitas:
- Control de flujos asíncronos:
- Evaluación diferida (Lazy evaluation):
- Programación concurrente:
7.1. Iteradores personalizados:
- Flexibilidad: Permiten crear iteradores que se adaptan a estructuras de datos complejas o a necesidades específicas de recorrido.
- Eficiencia: Generan valores bajo demanda, evitando cargar toda la estructura en memoria, lo cual es útil para grandes conjuntos de datos.
7.2. Generación de secuencias infinitas:
- Sucesiones numéricas: Posibilitan la creación de secuencias numéricas infinitas, como los números de Fibonacci o los números primos, sin necesidad de almacenarlas por completo.
- Datos dinámicos: Útiles para generar datos que se necesitan de forma gradual, como lecturas de sensores o resultados de cálculos complejos.
7.3. Control de flujos asíncronos:
- Lectura de datos: Facilitan la lectura de datos de fuentes asíncronas, como archivos o bases de datos, de manera más legible y manejable.
- Operaciones de red: Ayudan a gestionar respuestas de servidores o APIs de forma más eficiente, evitando bloqueos y mejorando la experiencia del usuario.
7.4. Evaluación diferida (Lazy evaluation):
- Cálculos eficientes: Permiten realizar cálculos solo cuando son necesarios, lo que ahorra recursos y mejora el rendimiento en situaciones donde no todos los resultados se utilizan.
- Optimización: Útil en algoritmos complejos o en el procesamiento de grandes cantidades de información, donde se prioriza la eficiencia.
7.5. Programación concurrente:
- Tareas simultáneas: Facilitan la gestión de múltiples tareas que se ejecutan de forma concurrente, mejorando la capacidad de respuesta de la aplicación.
- Procesos en segundo plano: Permiten ejecutar tareas en segundo plano sin bloquear el hilo principal, lo que es crucial para aplicaciones interactivas.
En resumen:
Las funciones generadoras son una herramienta versátil que permite escribir código más eficiente, legible y adaptable a diversas situaciones. Su capacidad para pausar y reanudar la ejecución, junto con la generación de valores bajo demanda, las convierte en una opción valiosa para optimizar el rendimiento y mejorar la experiencia del usuario en aplicaciones JavaScript.
8. Preguntas frecuentes y resumen sobre funciones generadoras en JS.
Las funciones generadoras permiten pausar y reanudar su ejecución. Usan la palabra clave yield para devolver valores de manera incremental. Se utilizan para manejar secuencias de datos, iteradores y procesos asincrónicos de manera eficiente.
Una función generadora se define con la sintaxis function*. Ejemplo: function* gen() { yield 1; yield 2; yield 3; }. Se ejecuta paso a paso con un iterador que controla su flujo.
Las funciones regulares ejecutan su código de una vez y devuelven un valor. Las generadoras, en cambio, pueden pausarse con yield y reanudarse con next(), permitiendo manejar secuencias de datos de manera más eficiente.
yield se usa dentro de una función generadora para pausar la ejecución y devolver un valor. Al llamar next(), la función continúa desde la última pausa. Ejemplo: yield "Hola"; detiene la ejecución y espera el siguiente next().
Para crear un iterador, se llama a la función generadora y se almacena su resultado en una variable. Ejemplo: const it = gen();. Luego, se usa it.next() para obtener valores de la secuencia generada.
El método next() avanza la ejecución de la función generadora y devuelve un objeto con value y done. Ejemplo: it.next() devuelve { value: 1, done: false } hasta que la función finaliza.
Permiten manejar grandes volúmenes de datos sin cargarlos en memoria, facilitan la creación de iteradores y mejoran la legibilidad en procesos asincrónicos. Son ideales para flujos de datos secuenciales o infinitos.
Se usan para crear secuencias infinitas, paginación de datos, generadores de identificadores únicos, lectura de archivos en fragmentos, control de flujos asincrónicos y simulación de streams de datos.
