En este tutorial, aprenderemos sobre los generadores y sus diferencias con las devoluciones de llamada.
¿Qué son los generadores?
Los generadores se han vuelto bastante famosos en Node.js en los últimos tiempos y eso probablemente debido a lo que son capaces de hacer.
- Los generadores son ejecuciones de funciones que se pueden suspender y reanudar en un momento posterior.
- Los generadores son útiles a la hora de realizar conceptos como 'ejecución diferida'. Esto básicamente significa que al suspender la ejecución y reanudarla a voluntad, podemos extraer valores solo cuando es necesario.
Los generadores tienen los siguientes 2 métodos clave
- Método de rendimiento: el método de rendimiento se llama en una función para detener la ejecución de la función en la línea específica donde se llama al método de rendimiento.
- Siguiente método: este método se llama desde la aplicación principal para reanudar la ejecución de una función que tiene un método de rendimiento. La ejecución de la función continuará hasta el siguiente método de rendimiento o hasta el final del método.
Veamos un ejemplo de cómo se pueden usar los generadores.
En nuestro ejemplo, tendremos una función Add simple que agregará 2 números, pero continuaremos deteniendo la ejecución del método en diferentes puntos para mostrar cómo se pueden usar los generadores.
function* Add(x) {yield x + 1;var y = yield(null);y = 6return x + y;}var gen = Add(5);gen.next();gen.next();
Explicación del código: -
- El primer paso es definir la "función" de nuestro generador. Tenga en cuenta que esto se hace agregando un "*" a la palabra clave de la función. Luego estamos definiendo una función llamada Agregar que toma un parámetro de x.
- La palabra clave de rendimiento es específica de los generadores. Esto lo convierte en una construcción poderosa para pausar una función en medio de cualquier cosa. Entonces, aquí, la ejecución de la función se detendrá hasta que invocamos la función next (), que se realizará en el Paso 4. En este punto, el valor de x se convertirá en 6 y se detendrá la ejecución de la función.
- Aquí es donde primero llamamos a la función de generador y enviamos el valor de 5 a nuestra función Agregar. Este valor se sustituirá en el parámetro x de nuestra función Agregar.
- Una vez que llamemos a la función next (), la función Add () reanudará la ejecución. Cuando se ejecute la siguiente instrucción var y = yield (null), la función Add () dejará de ejecutarse nuevamente.
- Ahora, después de volver a llamar a la función next (), se ejecutarán las siguientes declaraciones y se agregará y devolverá el valor combinado de x = 5 e y = 6.
Devolución de llamada frente a generadores
Los generadores se utilizan para resolver el problema de lo que se conoce como infierno de devolución de llamada. A veces, las funciones de devolución de llamada se anidan tanto durante el desarrollo de una aplicación Node.js que simplemente se vuelve demasiado complicado usar funciones de devolución de llamada.
Aquí es donde los generadores son útiles. Uno de los ejemplos más comunes de esto es cuando se crean funciones de temporizador.
Veamos el siguiente ejemplo de cómo los generadores pueden resultar útiles sobre las devoluciones de llamada.
Nuestro ejemplo simplemente creará una función de retardo de tiempo simple. Entonces querríamos llamar a esta función incorporando un retardo de 1000, 2000 y 3000 ms.
Paso 1) Defina nuestra función de devolución de llamada con el código de retardo de tiempo necesario.
function Timedelay(ptime, callback) {setTimeout(function() {callback("Pausing for " + ptime);}, time);}
Explicación del código: -
- Aquí estamos creando una función llamada Timedelay con un parámetro llamado ptime. Esto tomará el tiempo necesario que queremos introducir en nuestra aplicación.
- El siguiente paso es simplemente crear un mensaje, que se mostrará al usuario diciendo que la aplicación se detendrá durante esta cantidad de milisegundos.
Paso 2) Ahora veamos el código si estuviéramos incorporando devoluciones de llamada. Supongamos que quisiéramos incorporar devoluciones de llamada basadas en el valor de 1000, 2000 y 3000 milisegundos, el siguiente código muestra cómo necesitaríamos implementarlas usando devoluciones de llamada.
Timedelay(1000, function(message) {console.log(msg);Timedelay(2000, function(message) {console.log(msg);Timedelay(3000, function(message) {console.log(msg);})})})
Explicación del código: -
- Estamos llamando al Timedelay como una devolución de llamada con 1000 como valor.
- A continuación, queremos volver a llamar a la función Timedelay con 2000 como valor.
- Finalmente, queremos llamar a la función Timedelay nuevamente con 3000 como valor.
En el código anterior, puede ver que se vuelve más complicado ya que queremos comenzar a llamar a la función varias veces.
Paso 3) Ahora veamos cómo implementar el mismo código usando generadores. En el siguiente código, ahora puede ver lo simple que se ha vuelto implementar la función Timedelay usando generadores.
function* Messages() {console,log(yield(Timedelay(1000, function(){})));console,log(yield(Timedelay(2000, function(){})));console,log(yield(Timedelay(3000, function(){})));}
Explicación del código: -
- Primero estamos definiendo una función generadora que se utilizará para llamar a nuestra función Timedelay.
- Estamos llamando a la función Yield junto con la función Timedelay con 1000 como valor de parámetro.
- Luego, llamamos a la función Yield junto con la función Timedelay con 2000 como valor de parámetro.
- Finalmente, llamamos a la función Yield junto con la función Timedelay con 3000 como valor de parámetro.
Resumen
Los generadores también se pueden usar para aliviar los problemas con las devoluciones de llamada anidadas y ayudar a eliminar lo que se conoce como el infierno de las devoluciones de llamada. Los generadores se utilizan para detener el procesamiento de una función. Esto se logra mediante el uso del método 'rendimiento' en la función asíncrona.