Al igual que los generadores de Python , JavaScript también admite funciones de generador y objetos de generador.
Función de generador: una función de generador se define como una función normal, pero cada vez que necesita generar un valor, lo hace con la palabra clave yield en lugar de return. La declaración de rendimiento suspende la ejecución de la función y devuelve un valor a la persona que llama, pero retiene el estado suficiente para permitir que la función se reanude donde se dejó. Cuando se reanuda, la función continúa la ejecución inmediatamente después de la última ejecución de rendimiento.
Sintaxis:
// An example of generator function function* gen(){ yield 1; yield 2; ... ... }
Generator-Object: las funciones de generador devuelven un objeto generador. Los objetos generadores se usan llamando al siguiente método en el objeto generador o usando el objeto generador en un bucle «for of» (como se muestra en el programa anterior)
El objeto Generador es devuelto por una función generadora y se ajusta tanto al iterable protocolo y el protocolo iterador.
javascript
<script> // Generate Function generates three // different numbers in three calls function * fun() { yield 10; yield 20; yield 30; } // Calling the Generate Function var gen = fun(); document.write(gen.next().value); document.write("<br>"); document.write(gen.next().value); document.write("<br>"); document.write(gen.next().value); </script>
A continuación se muestra un código de ejemplo para imprimir series infinitas de números naturales usando un generador simple.
javascript
<script>// Generate Function generates an // infinite series of Natural Numbers function * nextNatural() { var naturalNumber = 1; // Infinite Generation while (true) { yield naturalNumber++; } } // Calling the Generate Function var gen = nextNatural(); // Loop to print the first // 10 Generated number for (var i = 0; i < 10; i++) { // Generating Next Number document.write(gen.next().value); // New Line document.write("<br>"); } </script>
Producción
1 2 3 4 5 6 7 8 9 10
A continuación se muestra un ejemplo de cómo regresar manualmente desde un generador
javascript
<script> var array = ['a', 'b', 'c']; function* generator(arr) { let i = 0; while (i < arr.length) { yield arr[i++] } } const it = generator(array); // we can do it.return() to finish the generator </script>
Encontrar rendimiento y sintaxis de rendimiento*
rendimiento: detiene la ejecución del generador y devuelve el valor de la expresión que se escribe después de la palabra clave de rendimiento.
yield*: itera sobre el operando y devuelve cada valor hasta que done sea verdadero.
javascript
<script> const arr = ['a', 'b', 'c']; function* generator() { yield 1; yield* arr; yield 2; } for (let value of generator()) { document.write(value); document.write("<br>"); } </script>
Producción
1 a b c 2
Otro método para crear iterables.
javascript
<script> var createOwnIterable = { *[Symbol.iterator]() { yield 'a'; yield 'b'; yield 'c'; } } for (let value of createOwnIterable) { document.write(value); document.write("<br>"); } <script>
Producción
a b c
Retorno de una función generadora
javascript
<script> function* generator() { yield 'a'; return 'result'; yield 'b'; } var it = generator(); document.write(JSON.stringify(it.next())); // {value: "a", done: false} document.write(JSON.stringify(it.next())); // {value: "result", done: true} </script>
Cómo lanzar una excepción desde el generador
javascript
<script> function* generator() { throw new Error('Error Occurred'); } const it = generator(); it.next(); // Uncaught Error: Error Occurred </script>
Llamar a un generador desde otro generador
javascript
<script> function* firstGenerator() { yield 2; yield 3; } function* secondGenerator() { yield 1; yield* firstGenerator(); yield 4; } for (let value of secondGenerator()) { document.write(value) document.write("<br>"); } </script>
Producción
1 2 3 4
Limitación de generadores
que no puede producir dentro de una devolución de llamada en generadores
javascript
<script> function* generator() { ['a', 'b', 'c'].forEach(value => yield value) // This will give syntax error } </script>
Uso de generadores asíncronos (para llamadas api)
javascript
<script> const firstPromise = () => { return new Promise((resolve, reject) => { setTimeout(() => resolve(1), 5000) }) } const secondPromise = () => { return new Promise((resolve, reject) => { setTimeout(() => resolve(2), 3000) }) } async function* generator() { const firstPromiseResult = await firstPromise(); yield firstPromiseResult; const secondPromiseResult = await secondPromise(); yield secondPromiseResult; } var it = generator(); for await(let value of it){ document.write(value); document.write("<br>"); } </script>
Producción
(after 5 seconds) 1 (after 3 seconds) 2
Ventajas de los generadores:
Son eficientes en memoria ya que tiene lugar una evaluación perezosa, es decir, retrasa la evaluación de una expresión hasta que se necesita su valor.
caso de uso (generadores)
- generadores de escritura en redux-saga
- async-await (Implementado con promesa y generadores)
Navegador compatible:
- Google Chrome 39 y superior
- Microsoft Edge 13 y superior
- Firefox 26 y superior
- Ópera 26 y superior
- Safari 10 y superior