Una discusión sobre los módulos de nodos está incompleta
sin hablar de devoluciones de llamada y manejo de errores.
¿ Qué son las devoluciones de llamada y por qué son esenciales para
soportar el cálculo asincrónico que es muy
útil cuando escribimos aplicaciones Node.js?
¿ Cómo se realiza el manejo de errores en las aplicaciones de Node?
Hablemos brevemente sobre esto en esta conferencia.
Antes de proceder a hablar sobre los módulos de nodo y las devoluciones de llamada,
necesitamos entender dos características destacadas sobre el lenguaje JavaScript en sí.
En primer lugar, JavaScript admite lo que se llama funciones de primera clase.
¿ Qué queremos decir con funciones de primera clase?
Es que una función puede ser tratada como cualquier otra variable.
Y por lo tanto, las funciones se pueden pasar como
parámetros dentro de las llamadas de función a otras funciones.
Y eso esencialmente nos permite enviar funciones como funciones de devolución de llamada que se pueden
llamar desde otro módulo de Node con el fin de realizar algún trabajo.
Luego mire cómo esto es muy útil para admitir devoluciones de llamada en Node.js.
El segundo aspecto sobre JavaScript es el soporte para cierres.
¿ Qué queremos decir con cierres?
Especialmente, si está familiarizado con los lenguajes de programación funcionales,
entiende cómo funciona el cierre.
Una función definida dentro de otra función
obtiene automáticamente acceso a las variables que se declaran en la función externa.
Entonces, incluso si la función externa se completa la ejecución,
cuando la función interna se ejecuta más adelante, la función interna todavía tendrá acceso a
los valores de las variables dentro de esa función externa.
Y esto se
usa de nuevo, de manera muy efectiva cuando usamos Callbacks en aplicaciones de Node.
Si está acostumbrado a la forma estándar de escribir aplicaciones,
entonces está familiarizado con el cálculo sincrónico donde
especifica un cálculo como un conjunto de pasos que se deben realizar uno tras otro.
Ahora, si organiza el cálculo de la siguiente manera,
como se muestra en el lado izquierdo de la diapositiva aquí,
tenemos el cálculo uno seguido de un cálculo de larga ejecución,
seguido por el cálculo dos y el cálculo tres.
Entonces, en este arreglo,
supongamos que el cálculo dos depende de que
el cálculo de larga ejecución complete su trabajo,
entonces tiene sentido que el cálculo dos espere hasta que se
complete el cálculo de larga ejecución antes de que se ejecute.
Ahora, podríamos tener otra pieza de
trabajo que se define por el cálculo tres. El
cálculo tres puede depender de ninguna manera del cálculo dos,
o del cálculo de larga ejecución para completar antes de ejecutarlo.
Entonces, en este caso,
si hacemos la ejecución sincrónica de este
cálculo, entonces el cálculo tres se atascará,
aunque de ninguna manera depende de la finalización del cálculo dos,
o el cálculo de larga ejecución.
Por lo tanto, la cantidad de trabajo que se debe hacer mediante el cálculo tres,
se retrasará debido a ninguna razón propia, ¿verdad?
En su lugar se retrasa debido a algo que lo precede en la secuencia de cálculo.
Ahora, el cálculo asíncrono, podemos reorganizar este trabajo de
tal manera que el cálculo uno, cuando se completa,
pueda generar esos cálculos de larga ejecución que se realizan detrás de las escenas de forma independiente,
y dado que el cálculo dos depende del cálculo de larga ejecución para terminar,
entonces el cálculo dos se puede ejecutar cuando finalice el cálculo de larga ejecución.
Ahora, esto libera el cálculo tres para continuar,
justo después de que termine el cálculo uno.
Así que esta forma de organizar,
asegura que el cálculo tres terminará mucho más rápido que
estar atascado detrás del cálculo de larga ejecución, y el cálculo dos.
Por lo tanto, este enfoque de reorganizar su trabajo es muy útil especialmente,
cuando tiene un cálculo de larga ejecución, especialmente, cómputos
enlazados de E/S que se deben realizar.
Entonces, en este caso, puede generar fuera del cálculo enlazado de E/S,
y cuando eso se complete,
entonces cualquier cosa que deba hacerse a partir de entonces,
se puede enviar a él como una devolución de llamada.
Por lo tanto, el cálculo dos se convertirá en
una devolución de llamada y luego se dará al cálculo de larga ejecución.
Entonces, cuando eso complete su trabajo,
devolverá la llamada a la función que está encerrada dentro de la devolución de llamada.
Así que esto es aprovechado de manera muy efectiva por Node.js al
reorganizar el cálculo dentro de nuestras aplicaciones Node.
Ahora, esto es muy,
muy útil cuando miramos la forma en que Node.js se ejecuta.
Entonces, como nos damos cuenta,
Node.js está organizado en un solo bucle de eventos subprocesos.
Este bucle de eventos de subproceso único, básicamente,
recoge las solicitudes a medida que entran y lo ejecutan una tras otra.
Siempre que necesite generar una solicitud de E/S,
la solicitud de E/S se generará
y cualquier trabajo que deba hacerse después de que se complete la solicitud de E/S,
se incluirá dentro de una devolución de llamada.
Entonces, cuando se complete la solicitud de E/S,
colocará la devolución de llamada en la cola de solicitudes,
y la devolución de llamada será manejada a partir de entonces,
por el bucle de eventos.
Entonces, el bucle de eventos es un bucle en ejecución continua
que básicamente recoge las solicitudes de la cola de solicitudes,
y luego las presta de una a la vez.
Entonces, cuando lo piensas,
te das cuenta de que Node.js es un único subproceso,
pero al mismo tiempo,
es capaz de lograr una tasa mucho más rápida de finalización del trabajo,
simplemente debido al uso juicioso de las devoluciones de llamada
y la ejecución asíncrona de solicitudes de E/S,
como para el archivo accesos o bases de datos,
o procesamiento de larga duración que se puede realizar de forma independiente detrás de escena.
Ahora, la forma en que el bucle de eventos Node.js maneja todo esto,
es que el bucle de eventos está organizado en una secuencia de fases.
Como puede ver en el diagrama que se muestra aquí,
las fases incluyen el manejo del temporizador, el manejo de
devolución de llamada de E/S, luego tiene inactivo, prepara,
luego la encuesta donde se manejan las solicitudes entrantes de conexiones o datos,
y luego la fase de comprobación,
y luego, finalmente, la fase de devolución de llamada de cierre.
Ahora, algunos detalles sobre lo que se hace en cada una de estas fases se enumeran en el lado derecho.
En la fase del temporizador,
el bucle de eventos maneja cualquier cosa que se active por la
función setTimeout () en JavaScript.
Las devoluciones de llamada de E/S se ejecutan,
casi todas las devoluciones de llamada que vuelven a
ejecutarse después de una solicitud de E/S serán manejadas por la cola de devoluciones de llamada de E/S.
Por lo tanto, cada una de estas fases mantiene su propia cola separada,
y el bucle de eventos Node.js recoge las solicitudes de cada una de estas colas y las maneja.
El, inactivo, preparar, está destinado para uso interno por Node.js.
La encuesta es donde recupera nuevos eventos de E/S para ser manejados y tal vez,
las solicitudes que llegan desde fuera.
La fase de devolución de llamada de cierre maneja los cierres de socket que necesitan ser manejados, y así sucesivamente.
Ahora, no necesitamos preocuparnos demasiado por
todos estos detalles si realmente necesitamos escribir una aplicación Node.js.
Cuando sea necesario, veremos algunos de estos detalles como y cuándo
es esencial para entender cómo funciona nuestra aplicación Node.
Pero por el momento, esto le da una visión general
de cómo se maneja el bucle de eventos Node.js.
Baste decir que esta es suficiente información para que podamos
entender las aplicaciones Node y cómo funcionan por el momento.
Si desea saber más detalles,
entonces le he dado un enlace a una descripción detallada en la
documentación Node.js que explica sobre el bucle de eventos con más detalle.
Con esta rápida comprensión del nodo, las
devoluciones de llamada y el manejo de errores,
pasaremos al ejercicio,
donde veremos cómo una aplicación de nodo puede escribir con devoluciones de llamada,
y cómo se pueden manejar los errores dentro de una aplicación de nodo.
Veremos el uso repetido de este patrón en ejercicios posteriores,
y lecciones posteriores específicamente,
cuando nos fijamos en Express,
y cómo construimos aplicaciones del lado del servidor usando Express con
más detalle en la parte posterior de este curso.