‫Profesor: Hola.
‫Ahora vamos a mostrar algunas páginas de error agradables a nuestros usuarios.
‫Y para empezar, primero creemos un error.
‫Así que abramos este recorrido aquí.
‫No, no quiero traducir.
‫Y ahora simplemente agreguemos algo a este registro aquí, y
‫entonces, por supuesto, no se encontrará.
‫Correcto, así es como se ve un error en
‫este punto.
‫Así que simplemente, todo este
‫JSON aquí, tal como se vería en Postman.
‫Así que hemos visto este tipo de error aquí antes.
‫Y entonces, ahora arreglemos eso.
‫Pero primero necesitamos corregir este error en particular.
‫Así que ahora tenemos,
‫no se puede leer el nombre de propiedad de nulo en getTour.
‫Bueno.
‫Y eso está aquí en nuestro controlador de vistas, getTour.
‫Y entonces aquí, no tenemos ningún manejo
‫de errores en caso de que no haya gira, ¿verdad?
‫Así que tenemos eso en todos nuestros otros controladores de
‫ruta, pero en esto, todavía no lo tenemos.
‫Así que agreguemos eso.
‫Entonces, si no hay un recorrido, regrese y vaya
‫al siguiente middleware con un nuevo error de aplicación.
‫Y probablemente aún no esté aquí.
‫Y no, de hecho, no lo es.
‫Así que const.
‫AppError es igual a.
‫Bien.
‫Error aquí por supuesto.
‫Y luego digamos
‫que no hay gira con ese nombre.
‫Y luego es un 404 por no encontrado.
‫¿Okey?
‫Intentémoslo de nuevo.
‫Y ahora deberíamos obtener un error mucho más agradable.
‫Y de hecho, obtenemos uno.
‫Entonces 404.
‫Y tenga en cuenta que este ahora es un error operativo.
‫Entonces, un error que sabemos que creamos nosotros mismos básicamente.
‫Y así, como antes, eso será importante para nuestra
‫estrategia de manejo de errores.
‫Entonces, hablemos de eso.
‫Y aquí hemos terminado.
‫Y ahora, en nuestro controlador
‫de errores, tenemos, recuerde, dos funciones que envían
‫errores al cliente.
‫Así que tenemos este aquí para el
‫desarrollo y este para la producción.
‫Luego, en producción,
‫distinguimos entre errores operativos y otros errores desconocidos.
‫¿Derecha?
‫Y eso es de lo que acabamos de hablar antes.
‫Entonces, para los errores
‫que conocemos, enviamos el mensaje de error real porque
‫podemos estar seguros de que no será
‫un error extraño
‫proveniente de alguna parte de Express o
‫Note o algo así.
‫Mientras que, por otro lado, cuando se trata de un error
‫desconocido, bueno, entonces no queremos filtrar los detalles del error.
‫Y ahora, en este caso, con
‫el sitio web renderizado, usaremos la misma estrategia.
‫Ahora, lo que voy
‫a hacer es simplemente agregar la representación de una página de
‫error a cada una de estas funciones.
‫Y, básicamente, lo que voy a hacer
‫es probar si la URL comienza con API de barra oblicua.
‫Entonces, en ese caso, enviamos este tipo de error, ¿verdad?
‫Pero si la URL no comienza con API, bueno, en ese caso, significa
‫que queremos representar una página de error como
‫un sitio web renderizado, ¿de acuerdo?
‫Así como lo hemos estado haciendo en esta sección.
‫De todos modos, ahora implementemos eso.
‫Y así, podemos usar la URL original del punto de solicitud.
‫Y probablemente lo hayamos usado antes.
‫¿Bien?
‫Entonces, la URL original es básicamente la URL completa, pero no
‫con el host.
‫Entonces se ve exactamente como la ruta.
‫Y, de nuevo, cuando accedemos a nuestra URL,
‫bueno, esa ruta comienza con la API de barra oblicua.
‫Y ahora podemos probar eso.
‫Entonces podemos usar una función de JavaScript llamada startsWith.
‫Entonces, una función que está disponible para cadenas.
‫Y luego prueba si comienza con barra API.
‫¿Derecha?
‫Y si lo hace, entonces esto es lo que queremos hacer.
‫Así que simplemente envíe el error como JSON.
‫Pero si no, bueno, entonces realmente queremos generar un error.
‫Entonces todavía es res. estado.
‫Y también a statusCode.
‫Pero aquí está renderizado.
‫Luego obtenemos el nombre de la
‫plantilla y vamos a crear esta plantilla en un
‫segundo, pero se llamará error.
‫Y luego, los datos que queremos enviar allí
‫son por ahora solo el título.
‫Y agregaré algunas cosas más
‫una vez que la plantilla esté lista.
‫Entonces, algo salió mal será el título de
‫esta página de error.
‫¿Bien?
‫Oh, en realidad no tenemos
‫acceso a la variable de solicitud aquí.
‫Y su función.
‫Y entonces agreguemos eso.
‫Solicite aquí.
‫Y también lo vamos a necesitar aquí.
‫Éste.
‫Y agreguemos eso aquí también.
‫Así que aquí mismo.
‫Bueno.
‫Entonces, ahora necesitamos crear esta página, o
‫esta plantilla, llamada error.
‫Y una vez más, ya tengo una plantilla sencilla para eso.
‫Entonces está en dev-data, templates y errorTemplate.
‫¿Okey?
‫Copiemos esto.
‫Y luego crea una vista para eso.
‫error. doguillo.
‫Bueno.
‫Y aquí tenemos un h2 simple que dice, uh
‫oh, algo salió mal.
‫Luego (risas) hay algunos emojis divertidos.
‫No son realmente divertidos.
‫Y luego aquí queremos poder transmitir también un mensaje.
‫¿Bien?
‫Así que agreguemos esto igual a msg, solo abreviatura de mensaje.
‫¿Bien?
‫Y eso es todo.
‫Así que cerremos eso y pasemos ese mensaje.
‫Entonces se establece msg.
‫Y realmente configurémoslo como mensaje de punto de error.
‫¿Okey?
‫Y lo estamos haciendo aquí porque estamos en desarrollo.
‫Así que tenlo en mente.
‫Agreguemos también algunos comentarios aquí.
‫API.
‫Pongamos eso aquí.
‫El sitio web renderizado.
‫Así que lo estamos haciendo así, con un mensaje de
‫error, nuevamente porque en
‫el desarrollo, realmente no importa si filtramos todos los detalles del
‫error a nuestra página, ¿verdad?
‫Porque nadie realmente lo verá ya que, sí,
‫estamos en desarrollo.
‫Entonces eso debería estar funcionando ahora.
‫Entonces, todo lo que debemos hacer ahora es volver a cargar esta página.
‫Pero ahora algo anda mal aquí.
‫Entonces dice que no envió ningún dato.
‫Así que volvamos aquí.
‫Bueno, como primer problema que veo
‫aquí, debería tener el código de estado y no solo el estado.
‫Eso es todo para comprobar si tenemos algún error aquí.
‫Oh sí.
‫Realmente hay errores.
‫Entonces, en realidad era el código de estado no válido.
‫Así que aquí debería estar el código.
‫Démosle otra salvada.
‫Vuelva a cargarlo.
‫Y ahora tenemos una página de error aquí.
‫Bueno, en realidad no está formateado.
‫Pero aún así, tiene el título y, lo
‫que es más importante, tiene este mensaje que acabamos de transmitir.
‫Entonces no hay gira con ese nombre.
‫Y eso viene exactamente de nuestro controlador de vistas.
‫Así que desde aquí.
‫Así que recuerde esa lógica en la que creamos un error aquí
‫que luego se transmite a nuestro error global
‫y al middleware Lint.
‫¿Derecha?
‫Y ese es el que recogerá
‫estos errores y se los enviará al cliente.
‫Ahora, en nuestro caso, obtenemos este
‫error porque aquí en nuestra plantilla, todavía nos
‫olvidamos de hacer algo.
‫Que es simplemente extender, por supuesto, nuestra plantilla principal.
‫¿Derecha?
‫Así que tenemos que decir extender a la plantilla base.
‫Y luego, como siempre, crea ese bloque aquí.
‫Así que bloquea el contenido.
‫Y luego todo esto debe estar ahí.
‫Y básicamente aquí estamos
‫haciendo exactamente lo mismo que hicimos en todas las otras plantillas.
‫Básicamente, inyectar este contenido aquí
‫en el blog de contenido en la plantilla base.
‫Entonces, si recargamos eso ahora, finalmente se verá como se esperaba.
‫¿Bien?
‫Y ahora, si realmente tuvimos algún error en nuestro código,
‫y entonces digamos nuevamente que no
‫tenemos este manejo de errores aquí, entonces,
‫por supuesto, todo el error se filtra al cliente.
‫Por lo tanto, no se puede leer el nombre de propiedad de nulo.
‫Y, por supuesto, no queremos que los visitantes de nuestro
‫sitio web obtengan este tipo de error, ¿verdad?
‫Nadie entendería realmente lo que eso significa.
‫Y así, en nuestro controlador de errores de producción,
‫ahora ocupémonos de eso.
‫Entonces aquí abajo en nuestro controlador de
‫errores, ahora apliquemos la misma lógica que tenemos aquí.
‫Así que probando si actualmente estamos manejando la API o no.
‫Y, por supuesto, podría haber formas más elegantes
‫de hacer esto.
‫Por ejemplo, podría tener un middleware de
‫manejo de errores completamente separado solo para la API
‫y uno para el sitio web renderizado, ¿verdad?
‫Pero de nuevo, solo quiero que sea un poco simple aquí.
‫¿Okey?
‫Entonces, en este caso, ese es realmente mi objetivo principal.
‫Bien.
‫Seleccionemos todo esto.
‫Oh, ¿qué pasó ahí?
‫Ah, aquí vamos.
‫Bueno.
‫Eso es para la API.
‫Y ahora realmente tendremos algo muy similar.
‫Entonces, este es, nuevamente, para el sitio web renderizado.
‫Llamémoslo B aquí y A para éste.
‫Así que solo para separarlo un poco mejor.
‫Entonces tenemos y luego B aquí abajo.
‫De todos modos, esto se verá un poco similar a este.
‫Entonces, si tenemos un error operativo, entonces, básicamente, la página de
‫error debería verse
‫como la que teníamos aquí antes.
‫Pero en caso de que sea un error de
‫programación o desconocido, entonces no queremos el mensaje completo, sino
‫solo un mensaje muy genérico.
‫Entonces, algo como, por favor, inténtalo de nuevo más tarde.
‫¿Bien?
‫Ahora veamos qué tipo de error obtenemos aquí.
‫Y aparentemente, obtenemos algo llamado una
‫declaración if solitaria aquí.
‫Derecha.
‫Entonces, sí, Lint realmente no
‫quiere que solo tengamos un if dentro de un bloque else.
‫Y estoy de acuerdo en que
‫no es una práctica de codificación hermosa.
‫Y así, de hecho, solucionaremos eso
‫deshaciéndonos de esto más aquí.
‫Dale una oportunidad.
‫Y luego ese error desaparece.
‫Pero ahora debemos asegurarnos de que esto realmente termine
‫el ciclo de respuesta a la solicitud.
‫Así que tenemos que volver aquí y aquí también.
‫Bien.
‫Ahora, otro error de ESLint, innecesario después de una devolución.
‫Y de hecho, eso también es cierto.
‫Y he estado siguiendo esta regla
‫a lo largo del curso porque me gusta a mí mismo
‫como práctica de codificación.
‫Y entonces, sí, deshagámonos de esta otra cosa aquí.
‫Realmente creo, y lo he creído durante mucho tiempo,
‫que se ve mucho mejor sin estas declaraciones if else, pero en
‫cambio solo con un if, como este aquí, y luego
‫incluir el else fuera de eso.
‫Bien, eso es lo que tenemos aquí ahora.
‫Pongamos también A y B aquí.
‫B.
‫Y de hecho, hagamos exactamente lo mismo aquí.
‫Así que regresa.
‫Devuelve este también.
‫Entonces aquí, A y B también.
‫Entonces, eso de hecho me parece más limpio.
‫Ahora tenemos A aquí y A aquí
‫de nuevo, pero bueno, no importa en este punto.
‫Bien.
‫Así que regresa aquí.
‫Regresa aquí.
‫Y antes de que me grite, eliminemos esto.
‫Y eso es mejor de nuevo.
‫Así que pon esto aquí.
‫Y eso debería ser realmente.
‫¿Bien?
‫Copiemos este comentario
‫aquí también, solo en aras de la exhaustividad.
‫Y luego llame a este B de nuevo.
‫Bien.
‫Perfecto.
‫Copiemos este aquí también en la
‫función de desarrollo.
‫Porque en este momento, una vez que devolvemos
‫ese error, realmente no tenemos forma de ver el error completo.
‫Muy bien, deshazte de esto para hacerlo más visible.
‫Y ahora eso es hermoso.
‫Bueno.
‫Así que dejémoslo aquí
‫ahora para que podamos iniciar nuestra aplicación de producción.
‫Básicamente ejecutándolo ahora en producción.
‫Y tenemos un script para
‫eso que se llama npm run start production.
‫¿Okey?
‫Entonces, si probamos esto ahora,
‫ya no deberíamos ver esta cadena aquí, ¿recuerdas?
‫Porque en este punto, no tenemos ningún manejo de errores
‫para un nombre de tour no válido como este.
‫¿Okey?
‫¿Derecha?
‫Ya que
‫estamos en producción y no es un
‫error operativo, bueno, no queremos ver esto.
‫Y eso es lo que codificamos antes.
‫Y, de hecho, este es el mensaje de error más genérico.
‫¿Derecha?
‫Pero si luego lo volvemos a colocar aquí en el controlador de vistas,
‫entonces, si volvemos a colocar este
‫manejo de errores, entonces, por supuesto, ya que
‫esto ahora será un error operativo, entonces obviamente obtendremos esa
‫cadena de error.
‫Porque siempre es
‫bueno mostrar un mensaje amigable al usuario.
‫Pero como vio, eso en realidad no sucedió.
‫Entonces, ¿por qué es eso?
‫Bueno, estamos en el error de producción.
‫Estamos en el sitio web renderizado.
‫Y de hecho, tenemos un error operativo.
‫Y entonces ...
‫Tenemos esto en su lugar.
‫Y, de hecho, debería funcionar como esperábamos.
‫Bueno, intentemos registrar en la consola el mensaje
‫del punto de error
‫solo para ver si realmente lo obtuvimos en este punto.
‫Bien.
‫Recarga a este tipo.
‫Y ahí está el error.
‫Pero aún así, eso es muy extraño.
‫Así que, de hecho, se registró el error completo.
‫Muy extraño.
‫Porque, por alguna razón, el mensaje tampoco está ahí.
‫Ejecútelo de nuevo en desarrollo.
‫Entonces npm start.
‫Bien.
‫Y aquí, por alguna razón, tiene acceso a este mensaje.
‫Eso significa que en nuestro controlador de
‫vistas, realmente configuramos ese mensaje correctamente.
‫Ejecútelo en producción nuevamente.
‫Así que este es el tipo de cosas que no nos gustan, ¿verdad?
‫Entonces, echemos un vistazo a dónde se crea realmente
‫nuestro error en la producción.
‫Y eso es aqui.
‫Entonces, este objeto de error que estamos usando aquí en
‫producción es una copia de este error, ¿verdad?
‫Entonces, el que está entrando en este middleware.
‫Entonces, echemos un vistazo a ambos en la
‫consola.
‫Entonces mensaje de punto de error.
‫Y luego también mensaje de punto de error.
‫Así que hazlo de nuevo.
‫Bueno.
‫Entonces vemos ese error, por
‫lo que el que está entrando directamente en nuestra función
‫de middleware, de hecho tiene el mensaje.
‫Pero luego el que copiamos, por lo que error, por
‫alguna razón no lo hace.
‫Entonces, este truco que estamos haciendo
‫aquí, por alguna razón, no copia el mensaje,
‫¿de acuerdo?
‫Entonces, hagamos una solución rápida a eso.
‫Y digamos que el mensaje de punto de error es igual al mensaje de punto de error.
‫¿Bien?
‫Y entonces eso debería arreglarlo, con suerte.
‫Ah bien.
‫Aquí vamos.
‫Derecha.
‫Así que ahora ves que de hecho son lo mismo.
‫Y ese era el problema.
‫¿Bien?
‫Entonces, sin esto, en
‫realidad, todos los errores no funcionarían correctamente.
‫Entonces, si publicamos esto aquí e
‫intentamos iniciar sesión, por ejemplo, admin @ natours. io.
‫Como puede ver, también obtenemos un error indefinido aquí.
‫Bien.
‫Y eso es nuevamente porque estamos en
‫producción y nuestro objeto de error no copió correctamente el mensaje.
‫No estoy seguro de por qué no capté
‫este cuando en realidad lo estábamos implementando.
‫Pero tal vez no lo probé de una manera lo suficientemente completa.
‫¿Okey?
‫Y de todos modos, si intentamos
‫esto ahora, obtendremos el mensaje de error correcto que
‫estamos esperando.
‫Bien.
‫Excelente.
‫Entonces eso está resuelto.
‫Y eso realmente concluye este video.
‫Entonces, como
‫conclusión, ahora tenemos una estrategia de
‫manejo de errores que funciona para el desarrollo, como antes, y
‫también para la producción.
‫Y luego, en cada uno de ellos, básicamente tenemos dos ramas.
‫Uno envía el mensaje de error para la
‫API, que es exactamente lo que
‫teníamos antes, y luego también tenemos ahora una especie de controlador
‫para el sitio web renderizado.
‫Y entonces, en ese caso, representamos nuestra plantilla de error.
‫Luego, en producción, también distinguimos
‫entre sitio web renderizado y API.
‫Y luego, al igual
‫que antes, dentro de cada una de
‫estas ramas, también distinguimos entre los
‫errores de operación y los errores desconocidos.
‫Tan operativo y desconocido.
‫Y luego por dentro renderizado, también operativo y desconocido.
‫Entonces, para el sitio web
‫renderizado, si tenemos un error operativo, entonces uno confiable,
‫entonces enviamos nuestro mensaje de error confiable.
‫Pero en caso de que no
‫confiemos en el
‫error, cuando no lo sepamos, simplemente enviamos este mensaje genérico al usuario.
‫Que bien.
‫Dejemos eso aquí y volvamos al desarrollo
‫y concluyamos esta conferencia.
‫Así que nos vemos en el próximo.