Transcripciones
1. Introducción: Bienvenido de nuevo al Módulo diez, registro y manejo
de errores de la serie de cursos Express JS. Mi nombre es Shawn Ragawnhi, Tú guía para A lo largo de los años, he construido aplicaciones
escalables y robustas para diversas industrias,
y en esta clase, te
ayudaré a abordar uno de los aspectos más críticos del desarrollo
de backend, el registro y los errores de manejo Uno de mis momentos de mayor alegría
fue cuando diseñé un sistema de registro que redujo tiempo de
depuración para
un cliente en un 60% El día de hoy, te mostraré
cómo lograr resultados similares. En este módulo, nos enfocaremos en identificar y manejar errores de
manera eficiente en Express s, simplificando el manejo de errores con herramientas como errores asíncronos Express,
registro de errores en
múltiples destinos
como archivos y MongoDB
para como archivos y MongoDB A continuación, manejar
excepciones no detectadas y rechazos
no manejados para
garantizar la estabilidad de la aplicación Y finalmente, extraeremos y organizaremos partes clave
de su aplicación que es el registro de rutas y configuración para una base de código limpia
y mantenible Esta clase es para desarrolladores
que desean construir aplicaciones
Express Jas
robustas y mantenibles Si has completado
los módulos anteriores, estás listo para sumergirte. Conocimientos básicos de JavaScript no Jas y express es todo
lo que necesitas para empezar. Al dominar el
manejo de errores y el registro, mejorará significativamente la confiabilidad de
sus aplicaciones También ahorrarás
incontables horas depurando, convirtiéndote en un desarrollador más eficiente
y valioso Finalmente, para el proyecto, construirás un amante personalizado para manejar registros en
múltiples transportes Eso es Console
Files y Manga DB. Y luego refaccionarás la
aplicación Fair Wheels extrayendo validación de
alegría y la
lógica del servidor en módulos separados Estas
tareas prácticas solidificarán su comprensión del
manejo de errores y la modularización Este módulo es un cambio de juego
para tus habilidades de
desarrollo de backend Vamos a sumergirnos y hacer que sus aplicaciones sean más
robustas que nunca. Nos vemos en la primera
conferencia, comencemos.
2. Introducción: registro y manejo de errores: En nuestra implementación actual
de la app de Fairwee, hemos asumido un mundo ideal donde todo
funciona No obstante, en el mundo real, siempre
hay errores
inesperados. Por ejemplo, es posible
que nuestra conexión con Mongo Deb se desprenda
por cualquier razón Entonces, como práctica recomendada, debe contar para estas situaciones
inesperadas y manejarlas correctamente, lo que significa que debe enviar un mensaje de error adecuado
al cliente y registrar la
excepción en el servidor. Entonces, más adelante, puedes mirar
el registro y ver cuáles son algunos problemas que están sucediendo con frecuencia y cómo
puedes mejorarlos. Así que permítanme demostrar un escenario del mundo real donde muere
nuestro servidor Mongo EV Entonces aquí en la terminal, se
puede ver que estoy ejecutando la
aplicación con Nord mod. Y aquí está mi otra ventana
terminal donde estoy dirigiendo Mongo Damon Se trata de un
servicio en segundo plano que está escuchando en el puerto 27017 Y aquí en Cartero, tengo una pestaña abierta para enviar
un get request api CR Entonces cuando enviamos esta solicitud, obtenemos una respuesta de 200. Hermoso. Ahora, de vuelta
en la terminal Mongo DB, voy a detener este proceso Así que déjame abrir una nueva ventana
Power Show y escribir top services name MongoDB. Y eso es todo. Nuestro servidor Mongo DV ahora
está cerrado. Veamos qué sucede cuando envías esta solicitud
una vez más. Entonces esto está colgando ahí. Después de unos segundos,
vamos a ver un mensaje de error en el terminal donde estamos
ejecutando la aplicación. Bien, así que aquí está
el mensaje de error. Error de selección del servidor de Mongo, selección
SRO agotó el tiempo de espera después, entonces tenemos una selección de servidor de
valor dinámico, tiempo de espera S. Y aquí está el error
real Entonces, por defecto, cuando te
conectas a Mongo DB, si
no se puede establecer la conexión, controlador
MongoDB intentará
reconectarse tres veces
con Si te desplazas hacia abajo hasta
la parte inferior de la página, C, nuestra aplicación se estrelló Eso significa que salimos del proceso con
el código uno. Ahora en esta
demostración en particular, apagué el MongAivServer, así que realmente no importaría si este proceso está en vivo Pero imaginemos en un escenario del mundo
real, nuestro servidor Manga Divi
va a caer por, digamos, 1 minuto, y luego va a volver después de 1 minuto Con la implementación actual, nuestro proceso de nodo
terminará y no podrá atender
a ningún otro cliente
incluso después de Mongo Divi resta Entonces este es un problema
y uno muy grande. Entonces necesitamos
manejar adecuadamente estos escenarios, y eso es lo que vamos
a aprender en esta sección.
3. Manejo de errores de selección de servidores: Ahora demos el primer paso para manejar este error correctamente. Entonces, siempre que vea
un error de selección del servidor, eso significa que el
cliente Manga B no puede
conectarse a ningún servidor en
la implementación de Mangaib Esto sucede por diversas razones como anillos de conexión incorrectos, problemas de
red,
mala configuración del servidor o incompatibilidad de versiones Tenga en cuenta que este error ocurrió cuando intentamos obtener
datos de la API del automóvil Entonces vayamos a nuestro módulo de autos. Este es el manejador para
obtener la lista de autos. Entonces aquí tenemos una promesa
que se devuelve aquí. Estamos esperando eso, pero en
ninguna parte de este código, tenemos un bloque try cache para
manejar promesas rechazadas. Esta implementación es
lo mismo que conseguir una promesa, llamar entonces, pero no llamar al
efectivo para manejar los errores. Entonces, si estás usando
la sintaxis prometida, siempre
debemos llamar
a caché para manejar excepciones. Si estás usando una
sincronización y Aviate, siempre
debes
tener r bloques de caché Entonces aquí, necesitamos poner este
código en un tri bloque como este y luego agregar el
bloque de caché donde obtenemos el error. Ahora aquí necesitamos enviar una respuesta
adecuada al cliente. Entonces responde ese estatus. Usamos el código de error 500, lo que significa error interno
del servidor. Entonces algo falló en el
servidor, no sabemos qué. Y luego mandar un mensaje
como si algo fallara. Ahora, técnicamente, aquí también
deberíamos registrar la excepción, pero vamos a
ver eso más adelante. Así que vamos a mejorar esta
aplicación paso a paso. Ahora, veamos cómo funciona esta
nueva implementación. Entonces de vuelta en la terminal, voy a iniciar Mangaibi primero porque si
no lo iniciamos y
ejecutamos la aplicación,
mira, no podemos
conectarnos a Entonces inicialmente, quiero estar
conectado con Mangaib y luego quiero dejar esa conexión en
algún lugar en el medio Entonces detengamos esta aplicación. Ahora de vuelta a la ventana de la terminal. Vamos a ejecutar inicio nombre
de servicio Mangaib. Ahora vamos a ejecutar nuestra aplicación de
ruedas justas. Bien, conectado a Manga DV. Voy a iniciar este proceso. Así que de nuevo,
nombre de servicio superior Manga DV. Entonces aquí en Post MD, voy a enviar una solicitud
para el punto final de autos. Esto va a
tomar 30 segundos, así que voy a pausar la
grabación y volver. Bien. Esto es lo que obtenemos. Error interno del servidor 500. Y este es nuestro mensaje. Ahora bien, si nos fijamos en la
ventana de terminal de nuestra aplicación, ya no
verá ese error de selección
del servidor, que resultó en la
terminación de este proceso.
4. Error en el middleware en Express: Entonces, en la última conferencia, dimos el primer paso para
manejar correctamente los errores. Pero hay un problema en
la implementación actual. Digamos que mañana decidimos cambiar el mensaje que
enviamos al cliente. Con la implementación actual, tenemos que pasar por cada manejador de
rutas donde
usamos este bloque Trcche
y modificar Entonces en una situación del mundo real, aquí vamos
a registrar el error. Nuevamente, si en el futuro, decidimos cambiar la forma en
que registramos el error
tenemos que volver a varios
manejadores de ruta y hacer ese cambio Entonces queremos mover esta lógica para manejar errores
a algún lugar central. Entonces, en el futuro,
queremos hacer un cambio en la lógica
para manejar errores. Hay un solo lugar
que necesitamos modificar. Así que vamos al punto índice g. Aquí es donde estamos registrando nuestras funciones de
middleware En Express, tenemos
un tipo especial de función de middleware
llamada error Registramos esa función de
middleware
después de todas las funciones de
middleware existentes Entonces aquí llamamos app that US y pasamos una función de middleware
con tres parámetros,
request response, y next Pero también agregamos un cuarto
argumento aquí al frente. Esa es la excepción o error que atrapamos en
otro lugar de la aplicación. Ahora en esta función, agregamos toda la lógica para manejar
errores en nuestra aplicación. Así que de vuelta a los autos Js. Voy a cortar esta lógica
desde aquí y pegarla aquí. Ahora, de vuelta a los autos
Js una vez más. Aquí en este bloque de caché, queremos pasar el control a nuestra función de
middleware de manejo de errores Entonces agregamos un nuevo
parámetro aquí, siguiente. Y como saben, llamamos
next para pasar el control a la siguiente función de middleware en procesamiento
de solicitudes Aquí en el bloque de caché, llamamos siguiente y pasamos este
error como argumento. Ahora bien, porque en index o Js, registramos esta función después de todas las funciones de
middleware existentes, cuando llamemos siguiente,
terminaremos aquí Y el error que pasemos
será el primer argumento
a esta función. Ahora con esta nueva
implementación, tenemos un solo lugar
para manejar errores. Entonces, si quieres hacer
cambios en el futuro, solo
regresamos y
modificamos esta función. En una aplicación del mundo real, la lógica para registrar
la excepción o los errores puede tener
varias líneas de largo. No queremos añadir todos los
detalles en index dot Js. Entonces en index o Js, solo
queremos
hacer orquestación. Queremos hacer un arreglo de alto
nivel. Los detalles deben ser encapsulados
en un módulo diferente. Entonces voy a
mover esta función,
esta función de middleware
a un módulo separado Así que aquí atrás, tenemos
esta carpeta de middleware. Vamos a agregar un nuevo archivo
aquí, error punto Js. Volviendo al índice Js, voy a obtener esta función
aquí y en error Js, establecer exportaciones de módulo
a esta función. Entonces ahora separamos los detalles del manejo de errores en
un módulo separado, y esto da como resultado una mejor
separación de las preocupaciones. En index o Js en la parte superior, necesitamos cargar este módulo. Así const error. Establecimos esto para que requiera. Después vamos un nivel
hasta la carpeta middleware, y descargamos el Y finalmente, aquí, llamamos app dot g y pasamos nuestra función de manejo de
errores. Tenga en cuenta que no estoy
llamando a esta función. Sólo estoy pasando una
referencia a esta función. Así que ahora nuestra aplicación
tiene un mejor diseño. No obstante, en cast o Js, tenemos este bloque try cache, y como puedes ver, tenemos que
repetir esto en cada
manejador de rutas en nuestra aplicación Tenemos que agregar este error de caché, y aquí deberíamos llamar a siguiente. Esto es repetitivo. Entonces,
en la próxima conferencia, voy a mostrarles cómo
mejorar esta implementación.
5. Elimina los bloqueos de intento y captura: En este manejador de rutas, tenemos un bloque try cache
para manejar errores El problema es que
terminaremos repitiendo este bloque try cache en
cada manejador de ruta individual Esto agrega mucho
ruido a nuestro código y hace que sea más difícil enfocarse en la lógica real de cada ruta. Es solo una distracción. Idealmente, queremos mover esta lógica de manejo de
errores de alto nivel en otro lugar a
una sola función que podamos reutilizar
en todas las rutas. Déjame mostrarte cómo
podemos hacer esto. Primero, crearemos una función reutilizable
llamada middleware asincrónico Esta función
servirá como plantilla. Incluirá el bloque tri
cache que necesitamos, pero lo haremos flexible que pueda adaptarse a
diferentes manejadores de ruta Entonces la función tomará como
argumento
un manejador de ruta como este Dentro del bloque tr, llamaremos a ese manejador Si algo sale mal, el bloque de caché pasará el error siguiente función de
middleware De esta manera, la única
parte que cambia para cada ruta es una
lógica específica en el manejador Todo lo demás permanece igual. Bien, definamos
este middleware asincrónico. Entonces esta función se
verá algo así. Toma un controlador de ruta
como argumento dentro, envolvemos el manejador
en un bloque de caché tr Si el controlador arroja un error, el bloque de caché llama a
continuación con la excepción Ahora usemos este
middleware en nuestra ruta. Entonces, en lugar de escribir ese bloque de
caché tr directamente
en el controlador de ruta, pasamos esta función
al middleware asincrónico Este middleware se
encargará del
manejo de errores por nosotros Así que no necesitamos
este siguiente parámetro, el bloque tr, y
el bloque de caché. Entonces nuestro código de ruta
se vuelve mucho más limpio. Ahora, mira esta función ASN,
la función anónima que estamos pasando como manejador
de rutas Finalmente, queremos pasar esta función ASN como
argumento a esta nueva función Ahora, debido a que handler es una función ASN,
deberíamos esperarla Y como hemos
usado esperar aquí, también
deberíamos marcar
esta función como AS. Ahora hay un pequeño tema
que debemos abordar. Al llamar al manejador
dentro de Async Middleware, necesitamos pasar la respuesta de
solicitud y los siguientes parámetros necesitamos pasar la respuesta de
solicitud y los siguientes parámetros.
Pero
aquí está la trampa. Esos objetos no están definidos en
ningún lugar en un middleware de sincronización Entonces, ¿cómo se obtiene acceso
a estos parámetros? Bueno, para resolver esto,
necesitamos entender
cómo funciona el express. Entonces aquí, cuando definimos
una ruta router punto get, digamos nueva ruta. Aquí pasamos una función de
manejador de ruta que toma tres parámetros, request response, y next, y va a una gráfica de código Entonces no llamamos a esta
función nuestras ventas. En cambio, pasamos una
referencia a esta función, y Express se encarga de llamarla y pasar
los argumentos requeridos. Eso es respuesta de solicitud
y siguiente en tiempo de ejecución. Pero en nuestra
implementación actual, estamos llamando directamente a
Async Middleware No es así como Express
espera que funcione. Tenemos que hacer un
pequeño cambio aquí. Entonces convertiremos esta función de middleware asíncrono
en una función Entonces, en lugar de llamarlo
directamente, haremos que devuelva
una nueva función. Esta
función devuelta actuará como el manejador de ruta real al
que Express puede llamar Por lo que esta nueva función devuelta aceptará la respuesta de solicitud, y siguiente como parámetros. Y dentro, llamará
al manejador original, pasamos a Middleware asincrónico, pasando por request
response y next Ahora, cuando Express llama a
esta función devuelta, proporcionará los objetos
necesarios. Eso es
respuesta de solicitud y siguiente, y todo va a
funcionar a la perfección. Con la configuración, hemos movido tricchblock
al middleware asincrónico Esto significa que nuestros manejadores de rutas
están ahora súper limpios. Estamos esperando la
llamada al manejador, así que necesitamos marcar
la función de llamada,
que es esta función como asíncrona Y ya no necesitamos aplicar este asincrónico aquí
ya que en
esta función en middleware
asincrónico en ninguna parte estamos
esperando una promesa, simplemente
estamos devolviendo
una simplemente
estamos devolviendo ¿Bien? Por último, hagamos reutilizable el middleware
asincrónico Entonces lo moveremos a un módulo separado aquí en
nuestra carpeta de middleware Vamos a crear un nuevo
archivo llamado Js asíncrono. Déjame cortar el código para
Async Middleware desde aquí y pegarlo aquí Por último, lo exportaremos
como exportaciones de pensamiento de módulo, y configuramos esto en un motor divertido. De vuelta aquí en Casta Js, simplemente cargue este artículo intermedio
Async Entonces en la parte superior, const middleware
asincrónico. Configuramos esto para requerir entonces la
carpeta middleware y Y eso es todo. Ahora puede usar este middleware en cualquier
manejador de rutas a través Entonces, con este enfoque,
tu núcleo se vuelve más limpio, más enfocado y
más fácil de mantener.
6. Uso del módulo de errores asyncos de Express: En la última conferencia,
definimos esta función de
middleware asincrónico Ahora bien, mientras esta función de
middleware asíncrono resuelve el problema de los bloques
repetitivos tr cach, el problema que tenemos es que tenemos que recordar
llamarlo cada Y esto también hace que nuestro
cable sea un poco ruidoso. Entonces en esta conferencia,
voy a mostrarles un enfoque
diferente. Vamos a
usar un módulo NPM,
y este módulo parcheará a nuestros
manejadores de ruta en Entonces, cuando enviamos una solicitud
a este punto final, ese módulo envolverá
nuestro código de manejador de ruta dentro de algo como esto Déjame mostrarte cómo funciona eso. Así que abre un terminal e
instala Express, errores asincrónicos. Vamos a instalar esto. Ahora,
vayamos a index o Js Necesitamos
cargar este módulo cuando se inicie
la aplicación. Entonces tendremos un requerimiento de errores asíncronos
expresos.
Eso es todo lo que tenemos que hacer. No hay que obtener el resultado
y almacenarlo en una constante. Ahora de vuelta en autos o JS, podemos eliminar la llamada a Aync Middleware y
volver a nuestra implementación original de
manejador de rutas, que es mucho De igual manera, voy a eliminar la segunda llamada
al middleware asincrónico Y por último, en la parte superior, voy a quitar también la declaración
requerida. Ahora probemos esto y asegurémonos de que esté
funcionando correctamente. Así que de vuelta en la terminal, voy a ejecutar nuestra aplicación
Fairwheels Ahora, en carteros, voy
a conseguir todos los autos. Entonces ese punto final está funcionando. Ahora voy a parar a Manga DB. Entonces aquí en la terminal Manga
Di B, detengamos esto con el nombre de
servicio superior Manga DB luego enviemos otra solicitud
al servidor para que vuelva a enviar. Esto va a
tomar un poco de tiempo. Bien, aquí está
la respuesta que
esperábamos un error 500
con este mensaje. Entonces esto verifica que este
módulo que instalamos correctamente movió el control de
un manejador de ruta a nuestra función de manejo de
errores Por lo que se puede ver el uso errores de
Express Aync
es muy, muy fácil Y este es mi
enfoque sugerido para manejar errores
asíncronos en manejadores de
rutas expresas Sin embargo, si este
módulo no funciona para su aplicación
por cualquier razón, entonces necesita volver a este otro enfoque y usar la función de middleware
asincrónico
7. Errores de registro: Este es nuestro middleware de error. Ahora, como les dije antes, en cada aplicación empresarial, necesitamos registrar las excepciones que se arrojan en
la aplicación. Así que después volvemos,
miramos el registro y veremos cuáles son las áreas de la aplicación que
podemos mejorar. Entonces en esta conferencia, voy a presentarles una
biblioteca maderera muy popular llamada Winston Entonces aquí está el Winston en NPM. La versión actual es 3.17. Y como pueden ver, ha
habido 13
millones de descargas
semanales. Es una biblioteca muy popular y rica en
funciones. Entonces comencemos. Aquí en la terminal, NPM
instala Winston Hermoso. Ahora, volvamos
a la página del NPM. Aquí puedes ver que la forma
recomendada de
usar Winston es
crear tu propio registrador Y a continuación, tenemos un
código de muestra para comenzar. Así que simplemente copiaré este código y lo modificaré de
acuerdo a nuestra app. Copia todo esto y
pégalo aquí en arrodt Js. En la parte superior, tenemos
nuestro módulo Winston. Entonces tenemos nuestro registrador, que se crea usando
este método create logger. Contiene un objeto
con pocas propiedades, nivel, formato,
meta por defecto y transportes Entonces déjame explicarte
cómo funciona esto. Primero, tenemos nivel de registro. Así que el nivel controla qué
registros se van a procesar. Eso significa que filtra
los registros por gravedad. Por lo que se supone que la severidad de todos
los niveles es numéricamente ascendente de lo más importante a lo menos importante Eso significa que si tenemos error, entonces tiene una severidad de cero y tenemos la prioridad
más alta. De igual manera, tenemos uno, info, STDP y verbos depurar y tontos con una
severidad de seis, y tiene la menor prioridad Entonces aquí hemos establecido el nivel
predeterminado en info, es
decir, todos los mensajes de info, advierten y error quedarán rezagados Y si establecemos el
nivel a verbos, entonces todos los mensajes de
verbos y por encima de los niveles
quedarán bloqueados A continuación, tenemos formato. Por lo que se utiliza un formato para
personalizar cómo aparecen los registros. Eso es un texto plano, un objeto JCN o con marca de tiempo Y hay más formatos, estos se implementan
en forma de registro, un módulo separado de Winston, y puedes echar un vistazo a este módulo para ver todos
los formatos disponibles Aquí vamos a usar el JCNFMat y no
necesitamos esta Ahora, este objeto logger tiene
una matriz de transportes. Entonces, un transporte es esencialmente un
dispositivo de almacenamiento para nuestros registros. Por lo que define dónde
se envían los registros. Winston viene con
algunos transportes centrales. Son Consola para
registrar mensajes en la pila de consola y HTTP para llamar a un
punto final SDDB para registrar mensajes También hay
plugins para Winston. Hay otros
módulos NPM para registrar mensajes en Mongo DB y COS DB, que es otra base de datos popular
sin SQL También hay un
complemento para registrar mensajes en Redis y Loge, que es un servicio muy popular de análisis y
monitoreo de
registros para aplicaciones
empresariales Ahora aquí vamos a utilizar
dos transportes diferentes, uno para registrar mensajes en un archivo y otro para
iniciar sesión en la consola Entonces déjame cambiar
esta a consola. Y no necesitamos esta propiedad de nombre de
archivo aquí. Nuestro registrador está listo para usar, y si solo
quieres tener un archivo de registros en formato JSON, este código es
suficiente para hacerlo. No obstante, hay
más en Winston. También es posible establecer un formato personalizado y un nivel personalizado en cada
transporte por separado. Y cualquier número de formatos se pueden combinar en un solo formato
usando el formato dot combine. Entonces voy a usar
algunos formatos en nuestros transportes y luego combinarlos para una
mejor experiencia Déjame mostrarte cómo hacer esto. En primer lugar, eliminemos
este nivel y formato predeterminados. Ahora en la consola, quiero usar colores para registrar niveles basados en
el mapeo personalizado. Para eso, podemos usar el formato de
colorar y
combinarlo con formato simple Entonces aquí, agregamos un formato de propiedad, y luego llamamos al método
combinado, el winston dot
format dot combine y simplemente pasamos los formatos
que queremos combinar Así winston dot
format dot colorIE y winston dot
format dot También queremos
darle un nivel de info. Entonces como mencioné antes, todos los mensajes de info
uno y niveles de error se
registrarán en la consola. Eso es. De igual manera, podemos personalizar nuestro transporte de
archivos. Como puede ver, el nivel personalizado ya
está configurado en error. Genial. Aquí, queremos que los registros sean más legibles
agregando fecha y hora actuales. Se puede hacer combinando formatos
timestamp y JCN. Entonces aquí, una vez más,
estoy llamando a combinar. Y luego pasar wstin
dot forma dot Time STAMP e instin
dot fam dot JCN Al hacerlo, hemos
agregado una marca de tiempo a cada error que pueda ocurrir
dentro del objeto JSN Finalmente, necesitamos usar este registrador en nuestro middleware de
error Entonces llamamos logger dot log. Luego pasamos un objeto
con un nivel de propiedad, que podemos establecer como error
o simplemente puedes usar el método de ayuda de error para registrar el error directamente. Así. Ahora, sólo tenemos que
pasar el mensaje de error. Entonces establecemos la
propiedad message para errar mensaje de punto. Ahora para demostrarlo, vayamos a los autos punto js. Aquí en la ruta get cars, voy a lanzar un error. Así que lanza nuevo error no es
capaz de buscar autos. Entonces imaginemos
en algún lugar de la aplicación, se arroja
un error con la implementación
actual. Nuestro middleware de error
atrapará esa excepción. Lo registrará usando Winston y devolverá el
error 500 al gravamen Entonces vamos a probar esto. Voy
a ejecutar la aplicación, Norman Beautiful. Ahora, de vuelta en cartero, enviemos una solicitud get
al punto final de autos Bien. Así que aquí está nuestro error
interno del servidor. Ahora bien, si nos fijamos en la consola, tenemos error porque usamos el método de error de punto
Winston, y su color es rojo Y este es el
mensaje de error que hemos arrojado, no capaces de ir a buscar autos Entonces este es el transporte de consola que hemos personalizado
en el registrador. Ahora en nuestro proyecto, puedes ver aquí tenemos este nuevo
archivo, error dot log. Aquí tenemos un objeto JSON
con un nivel de pocas propiedades, que es mensaje de error no es capaz de recuperar autos
y la marca Entonces, en el futuro, podrá
consultar el archivo de registro y tal vez extraer solo los
errores en una fecha específica. Entonces este es un panorama general. Simplemente llamamos logger dot error o uno de los métodos helper. Y dependiendo del transporte
que tengamos configurado, Winston registrará
el mensaje dado En la próxima conferencia, te
voy a mostrar cómo iniciar sesión en Mongo DB
8. Registro en MongoDB: Todo bien. Ahora déjame mostrarte cómo registrar mensajes
en Manga Deb El registro a Mangaib se hace bastante simple con
otro paquete de NPM, bastante simple con
otro paquete de NPM,
Winston Mangaib. Así
que vamos a instalarlo. NPM instalar Winston Mangaib. La versión 6.0 0.0. Así que asegúrate de tener exactamente
la misma versión. De lo contrario, lo que te voy a mostrar no va a
funcionar en tu sistema. De vuelta en E Js En
la última conferencia, agregamos archivos personalizados
y transportes de consola Ahora vamos a agregar un
nuevo transporte Manga Divi. Primero, tenemos que ir a la cima. Después de cargar Winston, necesitamos cargar Winston Manga DB
requieren Winston Manga requieren Winston Y aquí no nos importa lo que se
exporta de este módulo. Sólo tenemos que requerirlo. Bien con esto, podemos venir
aquí y llamar a logger punto en el nuevo Winston Dot transporta Manga B. Pasamos en opciones objeto hay algunas propiedades Aquí hay algunas propiedades que puedes consultar
en la documentación. El que
necesitas establecer es DB. Así que configuramos esto a la
cadena de conexión de nuestra base de datos, Manga DB holland 127.0 0.0 0.142 7017 Ahora en un escenario del mundo real, es posible que desee separar su registro de su base de datos
operativa. Esa es una decisión que varía de un
entorno a otro. Aquí, vamos a utilizar la misma base de datos para
registrar nuestros errores. Bien,
ya terminamos con esto. Ahora, no necesitamos
hacer ningún otro cambio. Entonces, la próxima vez que
haya un error en la aplicación porque
tenemos otro transporte, Winston
almacenará automáticamente nuestro error en Mongadib Así que volvamos a ejecutar la
aplicación. Y de vuelta en Cartero, enviar una solicitud al punto final
de autos Ahora, echemos un
vistazo a MongAV Compass. Así que aquí está nuestra base de datos
Fairwheel. Vamos a refrescarnos. Podemos ver que
tenemos un nuevo registro de colección, y este es el
mensaje que nos faltaba Entonces aquí está la marca de tiempo. El nivel se establece en error. Y aquí está el mensaje,
no es capaz de ir a buscar autos. Ahora en la última conferencia,
hablé de establecer un nivel personalizado en cada
transporte por separado. Entonces aquí, tal vez solo
quieras bloquear los
errores en Mongoib No desea
almacenar mensajes de información o
mensajes de depuración. Si ese es el caso, aquí
en el objeto options, también establece la
propiedad level en error. Entonces con esto, solo se registrarán
los mensajes de error. Ahora bien, como discutimos antes, si le dijiste esto a info, porque el nivel de información
tiene una prioridad de dos y es el tercero en
el nivel de registro, solo se
registrará la advertencia de error, y los mensajes de información. Nada más allá de la información
se registrará en Manga Divi.
9. Excepciones no atrapadas: Ahora bien, este middleware de error
que hemos agregado aquí solo capta errores que ocurren como parte de la
canalización de
procesamiento de solicitudes Entonces esto es particular
para Express. Si se lanza un error fuera
del contexto de Express, este middleware no será auto Déjame mostrarte. En la
parte inferior de este archivo, después de la exportación, voy
a lanzar un nuevo error. Así que lanza nuevo error, algo falló durante el arranque. Por lo que este error se arroja fuera del contexto de
procesar una solicitud. Está fuera del
contexto de Express. Entonces ahora, cuando ejecute
esta aplicación, verá que este error
se bloquea el proceso, y Winston no podrá
almacenarlo en el registro Para verificar esto, déjame
ir a nuestro archivo de registro, eliminar todo aquí, guardar
ahora de nuevo en la terminal. Ejecutemos nuestra aplicación. Norman, Bien, para que veas que nuestra app se estrelló, y aquí está nuestro error Algo falló durante la puesta en marcha. Y si miras el archivo de registro, puedes ver que aquí no
hay nada. Entonces, si implementas esta
aplicación en producción, tu aplicación no funcionará, y no hay forma de
que sepas qué salió
mal a menos que tengas acceso a la consola
en el servidor. Ahí es donde entra Winston. Le permite capturar y registrar excepciones sin cortar
sin esfuerzo Entonces en esta conferencia,
voy a mostrarles cómo manejar
adecuadamente las excepciones no capturadas en un proceso de nudo Esto es a un nivel superior. No está atado a expresar. Ahora, de vuelta en EOD o Js, aquí, al crear su registrador, agregue la propiedad de un
manejador de excepciones y pasarle una matriz con una instancia de
transporte Entonces manejadores de excepciones. Lo configuramos en una matriz donde
pasamos una instancia de transporte, nuevo Winston dot
transporta archivo Toma un objeto con
un nombre de archivo de propiedad. Y aquí queremos registrar las excepciones sin cortar
en un archivo separado Así que permítanme llamar a esto
excepciones dot log. Y eso es todo. Fácil, ¿verdad? Ahora bien, ¿y si ya ha
configurado un registrador y desea
habilitar el manejo de excepciones
más adelante? Eso no es problema. Puede utilizar excepciones método de manejador de
punto. Déjame mostrarte. Entonces voy a elogiar
esto y a continuación, después de definir nuestro logger, llamamos logger
dot exceptions punto handle y pasamos la instancia de transporte
como hicimos antes Así que nuevo transporta archivo punto. Nombre de archivo excepciones dot lag. Ahora bien, este enfoque es excelente para la flexibilidad a medida que su
aplicación evoluciona Por último, no queremos que nuestra aplicación estrelle después de registrar
la excepción sin cortar Por defecto, Winston sale del proceso después de registrar
la excepción
no capturada Puede deshabilitar este
comportamiento configurando exit on error property en falls
al crear su registrador. Entonces aquí, después de los manejadores de
excepciones, configuramos exit on error a falls, o puedes asignarlo
dinámicamente así El punto del registrador en el error es falso. Y permítanme comentar éste. Ahora, de vuelta a la terminal, corramos esto una vez más. Tenga en cuenta que esta vez el proceso no terminó porque aquí
cogimos la excepción. Entonces el proceso termina si no captas una excepción ¿Bien? Ahora, echemos un
vistazo a nuestro archivo de registro de excepciones. Puedes ver nuestro mensaje de error, algo falló durante el arranque. Con Winston, puede
administrar fácilmente excepciones sin cortes y controlar el comportamiento de nuestras
aplicaciones
durante errores inesperados En la próxima conferencia,
vamos a
ver los rechazos de
promesas inmanejables
10. Rechazos no manejados: En la última conferencia, hablamos sobre el manejo de excepciones
no capturadas Entonces, si hay una excepción
en tu aplicación y no
has captado esa excepción
usando un bloque de caché, puedes usar esta propiedad de
manejadores de excepciones
del registrador para registrarlo en
un archivo usando Winston Al igual que con las excepciones
no capturadas, Winston facilita almacenar en caché
y registrar rechazos no manejados Con la configuración actual, un rechazo
no controlado también se
registrará en nuestro archivo de
registro de puntos de
excepciones sin bloquear
la aplicación Déjame mostrártelo.
Entonces aquí en error punto Js, estamos lanzando una excepción. Sustituyamos esto por
una promesa rechazada. Tan constante promesa. Configuramos esto para prometer punto, rechazar y pasar un objeto de error con un mensaje,
promesa rechazada. Así que imagina que este
proceso representa el resultado de una operación
asíncrona como una llamada a una base de datos o un servicio TDP
remoto, y así Entonces tenemos una promesa rechazada. Y como te dije
antes, con promesas, o
llamamos entonces,
y luego deberíamos llamar
a catch para asegurarnos de
manejar rechazos, o si estamos usando la sintaxis
Ainc y esperar, esperamos la promesa, pero
debemos poner esto
en un try cachblock para caso de las excepciones En este código, tenemos una promesa, y voy a llamar luego
pasar una simple
consola de devolución de llamada punto log D. Pero
no voy a llamar a caché Entonces tendremos un rechazo
incontrolado. Ahora bien, si ejecutas la app Nomon
nuestra app está funcionando bien. Y si revisas el archivo de registro de
excepciones, aquí está nuestra promesa de
rechazo no manejada rechazada Entonces Winston automáticamente
captó esto como excepción no capturada y lo
registró en excepciones
dot log IL sin embargo,
con Winston, tiene manejadores de rechazo de propiedad para manejar los rechazos no manejados Déjame mostrarte cómo hacerlo. Aquí puede habilitar el
manejo de rechazo al
crear su registrador. Así que al igual que agregamos manejadores de
excepciones, podemos agregar
manejadores de rechazo y pasarle una variedad de incienso de
transporte Así que los manejadores de rechazo, lo
configuran en una matriz. Después pasamos nuevos Winston
dot transporta dot pile. Toma un objeto
con nombre de archivo. Ahora quiero registrar los
rechazos por separado. Entonces voy a llamarlo rechazos dot log,
y eso es todo. Esta configuración escribe todos
sus rechazos no manejados rechazos dedicados archivo de registro de
puntos Ahora bien, ¿y si ya
has configurado tu registrador y quieres manejar los rechazos de
promesas más tarde Al igual que el manejo de excepciones, Winston proporciona el método de manejo de
rechazos. Entonces déjame comentar
esto a continuación. Justo después de llamar a las excepciones de punto de
logger, llamamos logger punto
rechazos punto handle y simplemente pasamos una instancia de
transporte nuevo Winston punto ransport archivo
reacciones
dot Este enfoque
le permite agregar un transporte específicamente para rechazos incluso después de que
se inicialice su registrador Así que vamos a probarlo de nuevo en el
punto de índice del nodo terminal JS. Todo bien. Mira esta advertencia, rechazo
incontrolado. Y aquí está nuestro error. Ahora bien, si nos fijamos en el registro, tenemos un nuevo archivo
rechazos dot log Mira, aquí está nuestro rechazo de
promesa incontrolado, y esta vez, no está registrado en el archivo de registro de
puntos de excepciones Ahora con la
versión actual del nodo, este rechazo de promesa incontrolado debería terminar
el proceso de asentimiento Pero como puedes ver, este
proceso sigue en marcha. Estamos conectados a Mongo DB. Esto sucedió debido a
la propiedad exit on error en nuestro logger, que configuramos para caídas. Entonces, ya sea que esté lidiando con una excepción no capturada o
una reacción no controlada, como mejor práctica, debe terminar
el proceso de nodo Entonces deberías salir de aquí
porque en este punto, tu proceso puede estar
en un estado impuro Entonces, como mejor práctica, debemos terminar el
proceso y
reiniciarlo para asegurarnos de comenzar
con un estado limpio. Ahora bien, podría preguntarse, si
terminamos el proceso, ¿cómo vamos a
reiniciarlo en producción? Bueno, hay herramientas para eso, que llamamos gestores de procesos. Y en el futuro,
vamos a mirar uno de esos. Entonces voy a
modificar este código, y simplemente eliminamos la propiedad exit on error
porque por defecto, Winston saldrá después de registrar una excepción no capturada o
un rechazo incontrolado Una pregunta que podrías
tener es si debes registrar los mensajes en un archivo o en
una base de datos como Manga Div. Hay diferentes
opiniones al respecto, pero personalmente
creo que deberías usar ambos transportes
porque cada transporte tiene fortalezas y debilidades Manga Di B u otras bases de datos
son buenas para quering datos. Entonces, si quieres crear una aplicación cliente
para consultar tu registro, es mucho más fácil
consultar los datos en
Mongo DB en lugar de
un archivo plano como No obstante, es posible
que tu servidor Mongo DB se caiga o
no puedas conectarte a él
por cualquier motivo En ese caso, es mejor usar el sistema de archivos porque el
sistema de archivos siempre está disponible. En un ambiente de producción, rechazos de promesas
inmanejables pueden pasar desapercibidos sin Entonces de esta manera, creamos una pista de auditoría de lo que
salió mal y por qué. Y así es como manejas los rechazos
inmanejables con Winston Ya sean excepciones sin cortes
o rechazos de promesas, Winston le ayuda a mantener la visibilidad y confiabilidad
en
11. Extraer rutas: Bien, así que aquí está el
código en index o Js. El tema principal que tenemos aquí es la falta de separación
de preocupaciones. Aquí están sucediendo tantas
cosas, y por eso tenemos
una gran cantidad de declaraciones
requeridas en
la parte superior de este módulo. Debajo de eso, puedes ver que
tenemos algún código de configuración. Después de eso, tenemos
algo completamente diferente, que se trata de conectarnos
a la base de datos Mongo Di Ba Luego pasamos a configurar nuestras rutas en
varios middleware Estas son preocupaciones diferentes. No deben
mezclarse en un archivo o en un solo módulo. En este módulo,
sólo debemos orquestar estas preocupaciones Por lo que los detalles de ellos deben trasladarse a
diferentes módulos. Por ejemplo, los detalles
de configuración de rutas o los detalles de conexión a base de datos
Mongo DB,
deben estar separados Entonces en esta conferencia, nos
vamos a centrar en extraer rutas en
un módulo separado. Así que vamos a crear una nueva
carpeta llamada initialize. Aquí, voy a agregar un
nuevo archivo rutas punto JS, y aquí deberíamos
exportar una función. Así módulo dot Exportaciones. Ponemos esto a una función. Ahora, en esta función,
voy a agregar todo el código para configurar nuestras rutas y otro middleware Así que de vuelta en index o Js, voy a cortar todo el
código y moverlo aquí. Así que mira las
dependencias aquí. Tenemos una dependencia al objeto
app para expresar, todos estos routers,
como empresas ,
clientes, etc. Así que de vuelta en index o Js
en la parte superior en la línea 14, así es como creamos
el objeto app. Deberíamos tener una sola instancia de eso en
toda la aplicación. En otras palabras, no
queremos cargar Express y luego llamarlo para crear un
objeto app en nuestro nuevo módulo. Por lo que queremos enviar
una referencia a esta app a este nuevo módulo. Entonces esta función debería
tomar app como argumento. ¿Bien? Ahora, de vuelta en index o Js, aquí tenemos el objeto app. Podemos cargar nuestro nuevo módulo
que es rutas inicializadas. Esto devuelve una función, por lo que la llamamos y pasamos el objeto
app. Eso es. Es todo lo que tenemos que hacer. Ahora
vamos a limpiar este módulo. Entonces todos estos enrutadores
que aquí hemos importado, como
empresas, clientes, etc., todos estos
deben trasladarse a nuestro nuevo módulo porque
no los hemos referenciado en ningún
otro lugar del módulo de índice. Así que recorta aquí,
pégalos en la parte superior. Hemos agregado la mayoría
de las dependencias. También necesitamos Express y
el error middleware. Así podemos cargar el Express
en la parte superior, const Express. Requerir Express. Ahora para el error middleware, voy a sacarlo de
index o Js porque este es
el único lugar en el que estás
haciendo referencia a esta el único lugar en el que estás haciendo referencia Aquí está nuestro middleware de error. Reduzca en rutas o Js, y agreguemos eso aquí. Ahora, volviendo a index o Js, se
puede ver que el
core en este módulo ya
es mucho más corto. Ya no tenemos tantas declaraciones
requeridas, y además la implementación
es un poco más limpia. Ahora una última cosa
volver al módulo de rutas, necesitamos cambiar las rutas a estos enrutadores porque
la carpeta rutas no
está dentro de la carpeta
inicializada Entonces en cualquier lugar que tengamos peri slash, voy a reemplazar eso
con periodo periodo Entonces aquí he seleccionado
estos dos personajes. En el código VS, podemos habilitar la edición de
múltiples cursor. Estoy manteniendo pulsado Control
y D en Windows. Si estás usando
Mac, el atajo probablemente
sea Comando D. Así que mira, estoy seleccionando varias instancias y luego podemos
reemplazarlas todas de una vez. Así periodo periodo. Hecho.
12. Extraer la lógica de registro: Aquí está nuestro error Js middleware. En esta conferencia,
vamos a mover todo el código para configurar registro con diferentes módulos. Eso es todo lo que esté
relacionado con Winston y manejo promesas
rechazadas y excepciones
no capturadas Entonces, en la carpeta inicializada, agreguemos un nuevo archivo, loguemos dot js, y luego
volvamos al error dot js Toma todo este código para
configurar Winston. Consígalo y muévelo a los puntos de
registro aquí mismo. Ahora, debemos exportar este logger, así módulo dot Exportaciones. Y queremos llamarlo Logger. Entonces logger, configuramos
esto en Logger. Ahora volvemos al índice punto js. También me gustaría mover esta sentencia require para manejar
errores asíncronos en Express Prefiero poner esto
en nuestro módulo de registro, que se trata de manejar
y errores de registro. Así que vamos a cortarlo de aquí y pegarlo en el módulo
logging dot js. Ahora, finalmente,
tenemos que volver al index dot js y cargar
el módulo de registro. Requerir inicializa Logging. Tenga en cuenta que pongo esto primero. Así que por si acaso obtenemos un error
en la carga de otros módulos, para asegurarnos de bloquear ese error y
terminar el proceso. Entonces terminamos con esta
refactorización como ejercicio. Quiero que muevas todo
el código para tratar con la inicialización de la
base de datos a un módulo separado
llamado dbdt Js Tendrás mi solución
en la próxima conferencia.
13. Extraer la lógica de la base de datos: Aquí en el punto índice JS, este es el único código que
tenemos para la
inicialización de la base de datos Entonces aquí en la carpeta
inicializada, agreguemos un nuevo archivo, dw dot JS Y aquí vamos
a exportar una función. Así módulo dot Exportaciones. Ponemos esto a una función. Y luego mover todo el código de
inicialización de la base de datos aquí mismo Ahora, voy a hacer
algunos cambios aquí. En primer lugar, cuando nos conectamos, no
quiero hacer
Consultar en registro. Prefiero registrar esto como un mensaje informativo
usando Winston Entonces, en la parte superior, carguemos nuestro
registrador para requerir Logging. Y necesitamos
desestructurar logger, así que Canst Cebrass Entonces, ¿por qué lo estamos reestructurando? Si recuerdas, en
el logging dot js, hemos asignado
el objeto logger como una propiedad de
module dot export. Entonces, para acceder a la propiedad del
registrador, es
necesario desestructurarla. Lo hice a propósito
para un rápido repaso. Ahora volvemos a db dot js. Como tenemos nuestro registrador ahora, podemos reemplazar esta consola que registra con logger dot info. También debemos eliminar
este método de caché porque si no podemos
conectarnos a Mongo Di B, queremos registrar esa excepción
y terminar el proceso Con la implementación actual, estamos manejando esta promesa
rechazada aquí mismo, y todo lo que estamos haciendo es mostrar este mensaje
en la consola. Entonces no vamos a registrar esto. No estamos terminando
el proceso. Yo uso esto aquí específicamente
con fines de demostración, pero con la nueva implementación, no
necesitamos esto. Entonces eliminemos
esto y finalmente, necesitamos importar
mangosta en la parte superior Voy a sacar esto
del módulo indexado o Js. Así que de vuelta en indexado
o Js en la parte superior, voy a quitar
esta línea para importar mangosta y luego
ponerla aquí mismo Así que aquí está nuestro módulo de base de datos. Se puede ver que el código está
muy limpio, muy corto. Tenemos una sola responsabilidad. No tenemos demasiadas
cosas mezcladas. Por último, necesitamos cargar
este módulo en index o Js. Entonces aquí, voy a llamar
requerir inicializar DV. Aquí obtenemos una función,
entonces la llamamos. Ahora verifiquemos eso con
nuestra implementación actual. Si no podemos conectarnos
a la base de datos durante la
inicialización de la aplicación, se
registra
esa excepción y se
terminará el proceso Así que abre una nueva terminal. Voy a detener el proceso
Mongo DB con nombre de servicio de
parada Mongo DV Y luego de vuelta a nuestra ventana
terminal, nodo, indexado o Js Así que aquí está
nuestro rechazo inmanejado Se termina el proceso. Y si nos fijamos en
rechazos dot log, podemos ver que el rechazo
se registra aquí. Hermoso. Entonces por eso te dije deberíamos eliminar
el método de caché aquí y dejar que nuestro manejador de errores
global ocupe de esa promesa rechazada Aquí está tu próximo ejercicio. Quiero que vuelvas
a index o Js y extraigas todo el código para lidiar con la configuración
a un módulo separado. Entonces más específicamente, estoy hablando de estas pocas
líneas aquí donde
buscamos los ajustes de
configuración esenciales
durante la
inicialización de la aplicación Verás mi solución a continuación.
14. Extraer la lógica de configuración: Todo bien. Empecemos agregando un nuevo archivo en la carpeta
inicializada Entonces config dot js. Nuevamente, exportamos una función. Ahora, de vuelta en index o Js, tomamos todo el código para registrar los ajustes de configuración
en este nuevo módulo. Así que aquí tenemos una dependencia
a este módulo de configuración. Entonces voy a obtener esto de index dot js y cargarlo
en la parte superior de este módulo. Bien, así que si no tenemos
esta configuración, no
queremos iniciar sesión
en la consola. Más bien, queremos almacenar esto como un
error fatal en nuestro registro. Entonces, en lugar de hacer un error de punto de consola
y una salida de punto de proceso, es mejor
lanzar una excepción, y entonces nuestra
infraestructura actual atrapará esa excepción, registrará y terminará
el proceso. Entonces lanzamos un nuevo error
y usamos el mensaje de error. Además, como mejor práctica, siempre arroja objetos de error
en lugar de cadenas, aunque puedas
hacerlo en JavaScript. Porque cuando arrojas
un objeto de error, este seguimiento de pila estará
disponible para que lo veas más adelante. Si lanza una cadena
con el mensaje de error, no
tendrá
el seguimiento de pila. Bien, entonces esa es otra mejor
práctica para que la conozcas. Ahora por fin, volvamos a index o Js y carguemos
este nuevo módulo. Por lo tanto requieren inicializar,
flash config. Es una función, entonces la llamamos. Ahora, vamos a probarlo. Antes de eso, necesito
iniciar el servicio Manga DV. Así que de vuelta en la
terminal, vamos a ejecutar el nombre del servicio de
inicio Manga DV. Bien, ahora tenemos que
empezar de nuevo. Así que cierra todas las terminales
y abre una nueva terminal
así y ejecuta nod index dot JS Bien, así se termina el
proceso, pero no se registra nada
en la consola. Aunque si
miras este archivo, puedes ver por qué se estrelló nuestra
aplicación Error de Patel, la
clave secreta JWD no está definida. Esto es bueno para un ambiente
de producción. Pero si le das
esta aplicación a un nuevo desarrollador y ellos la ejecutan, no
tienen idea de
lo que está pasando. Entonces, en nuestra
implementación actual, estamos usando solo
un transporte de archivos para excepciones no capturadas Por lo que
también debemos agregar un transporte de
consola para mostrar
excepciones no capturadas en la consola Así que la nueva consola Winston dot transporta
. Y eso es todo. Volvamos a la terminal y ejecutemos la aplicación
una vez más. Puedes ver la razón por la que falló
nuestra aplicación es porque no hemos
definido la clave privada JWT Ahora quiero
mostrarte algo. Así que vuelve al índice punto js. Mira el archivo JS del punto índice. Aquí solo tenemos 13
líneas de código. ¿Recuerdas lo que teníamos antes? Creo que teníamos de 30 a 40 líneas de código con una
separación muy pobre de preocupaciones. Con esta nueva refactorización, estamos haciendo una sola cosa, configurando la aplicación Los detalles del registro, los detalles de las rutas, los detalles de la base de datos y otros aspectos se
delegan a otros módulos. Este es un
principio único de responsabilidad en la práctica. Aunque todavía hay
margen para la refactorización, podemos mover esta configuración
de joy y este código aquí, que se
encarga de manejar la configuración del servidor
e iniciarla Por lo que se lo dejaré para usted como una asignación
de esta sección.