Cuando comencé a trabajar con Express y traté de descubrir cómo manejar los errores, tuve dificultades. Había una sensación de que nadie escribió sobre lo que necesitaba. Como resultado, tuve que buscar respuestas a mis preguntas yo mismo. Hoy quiero contar todo lo que sé sobre el manejo de errores en aplicaciones Express. Comencemos con errores sincrónicos.

Manejo sincrónico de errores
Si necesita manejar un error síncrono, puede, en primer lugar, usar la instrucción
throw
,
throw
dicho error en el controlador de solicitud Express. Tenga en cuenta que los controladores de solicitudes también se denominan "controladores", pero prefiero utilizar el término "controlador de solicitudes", ya que me parece más claro.
Así es como se ve:
app.post('/testing', (req, res) => { throw new Error('Something broke! ') })
Dichos errores pueden detectarse utilizando el controlador de errores Express. Si no ha escrito su propio controlador de errores (hablaremos más sobre esto a continuación), Express manejará el error utilizando el controlador predeterminado.
Esto es lo que hace el controlador de errores Express estándar:
- Establece el código de estado de respuesta HTTP en 500.
- Envía una respuesta de texto a la entidad que ejecuta la solicitud.
- Registra una respuesta de texto en la consola.
Mensaje de error mostrado en la consolaManejo asincrónico de errores
Para manejar errores asincrónicos, debe enviar un error al controlador de errores Express a través del
next
argumento:
app.post('/testing', async (req, res, next) => { return next(new Error('Something broke again! ')) })
Esto es lo que llega a la consola al registrar este error.
Mensaje de error mostrado en la consolaSi usa la construcción async / await en una aplicación Express, necesitará usar una función de contenedor como
express-async-handler . Esto le permite escribir código asincrónico sin bloques
try / catch . Lea más sobre async / await en Express
aquí .
const asyncHandler = require('express-async-handler') app.post('/testing', asyncHandler(async (req, res, next) => {
Después de que el controlador de solicitud se envuelva en
express-async-handler
, puede, como se describió anteriormente, lanzar un error utilizando la instrucción
throw
. Este error irá al controlador de errores Express.
app.post('/testing', asyncHandler(async (req, res, next) => { throw new Error('Something broke yet again! ') }))
Mensaje de error mostrado en la consolaEscribir su propio controlador de errores
Los manejadores de errores expresos toman 4 argumentos:
- error
- req
- res
- siguiente
Debe colocarlos después de controladores intermedios y rutas.
app.use() app.get() app.post() app.put() app.delete()
Si crea su propio controlador de errores, Express dejará de usar el controlador de errores estándar. Para manejar el error, debe generar una respuesta para la aplicación front-end que abordó el punto final en el que ocurrió el error. Esto significa que debe hacer lo siguiente:
- Genere y envíe un código de estado de respuesta adecuado.
- Formule y envíe una respuesta adecuada.
El código de estado apropiado en cada caso particular depende de lo que sucedió exactamente. Aquí hay una lista de errores comunes que debe estar preparado para manejar:
- Error
400 Bad Request
. Usado en dos situaciones. En primer lugar, cuando el usuario no incluyó el campo requerido en la solicitud (por ejemplo, el campo con la información de la tarjeta de crédito no se completó en el formulario de pago enviado). En segundo lugar, cuando la solicitud contiene datos incorrectos (por ejemplo, ingresar diferentes contraseñas en el campo de contraseña y en el campo de confirmación de contraseña). - Error
401 Unauthorized
. Este código de estado de respuesta se aplica si el usuario ha ingresado credenciales incorrectas (como nombre de usuario, dirección de correo electrónico o contraseña). - Error
403 Forbidden
. Se utiliza cuando el usuario no tiene acceso al punto final. - Error
404 Not Found
. Se utiliza en casos donde el punto final no se puede detectar. - Error
500 Internal Server Error
Error 500 Internal Server Error
. Se aplica cuando la solicitud enviada por el front-end se forma correctamente, pero se produjo algún error en el back-end.
Después de definir el código de estado de respuesta apropiado, debe establecerse usando
res.status
:
app.use((error, req, res, next) => {
El código de estado de respuesta debe corresponder al mensaje de error. Para hacer esto, envíe el código de estado junto con el error.
La forma más fácil de hacer esto es con el paquete
http-errors . Permite enviar tres datos por error:
- El código de estado de respuesta.
- El mensaje asociado con el error.
- Cualquier dato que deba enviarse (esto es opcional).
Aquí se explica cómo instalar el paquete de
http-errors
:
npm install http-errors --save
Aquí se explica cómo usar este paquete:
const createError = require('http-errors')
Considere un ejemplo que le permitirá comprender esto correctamente.
Imagine que estamos tratando de encontrar un usuario en su dirección de correo electrónico. Pero este usuario no se puede encontrar. Como resultado, decidimos enviar un error de
User not found
en respuesta a la solicitud correspondiente, informando a la persona que llama que no se encontró al usuario.
Esto es lo que necesitaremos hacer al crear el error:
- Establezca el código de estado de respuesta en
400 Bad Request
(después de todo, el usuario ingresó datos incorrectos). Este será nuestro primer parámetro. - Envíe un mensaje a la persona que llama como
User not found
. Este será el segundo parámetro.
app.put('/testing', asyncHandler(async (req, res) => { const { email } = req.body const user = await User.findOne({ email })
Puede obtener el código de estado usando la construcción
error.status
y el mensaje de error usando
error.message
:
El resultado de errores de registro en la consolaLuego, el estado de respuesta se establece usando
res.status
, y el mensaje se escribe en
res.json
:
app.use((error, req, res, next) => {
Personalmente, prefiero enviar un código de estado, un mensaje y el resultado del seguimiento de la pila en tales respuestas. Esto facilita la depuración.
app.use((error, req, res, next) => {
▍ Código de estado de respuesta predeterminado
Si la fuente del error no es
createError
, entonces no tendrá la propiedad de
status
. Aquí hay un ejemplo en el que se intentó leer un archivo inexistente usando
fs.readFile
:
const fs = require('fs') const util = require('util')
Tal objeto de error no tendrá la propiedad de
status
:
app.use((error, req, res, next) => { console.log('Error status: ', error.status) console.log('Message: ', error.message) })
El resultado de errores de registro en la consolaEn tales casos, puede establecer el código de error predeterminado. Es decir, estamos hablando del
500 Internal Server Error
:
app.use((error, req, res, next) => { res.status(error.status || 500) res.json({ status: error.status, message: error.message, stack: error.stack }) })
▍ Cambiar el código de estado de error
Supongamos que vamos a leer un determinado archivo utilizando los datos proporcionados por el usuario. Si dicho archivo no existe, significa que debemos dar un error
400 Bad Request
. Después de todo, no se puede encontrar el servidor porque no se puede encontrar el archivo.
En este caso, debe usar la construcción try / catch para detectar el error original. Luego debe volver a crear el objeto de error usando
createError
:
app.get('/testing', asyncHandler(async (req, res, next) => { try { const { file } = req.body const contents = await readFilePromise(path.join(__dirname, file)) } catch (error) { throw createError(400, `File ${file} does not exist`) } })
▍ 404 manejo de errores
Si la solicitud pasó por todos los controladores y rutas intermedios, pero no se procesó, esto significa que no se encontró el punto final correspondiente a dicha solicitud.
Para manejar los errores
404 Not Found
, debe agregar, entre las rutas y el controlador de errores, un controlador adicional. Así es como se ve la creación del objeto de error 404:
Detalles del error▍ ERR_HTTP_HEADERS_SENT notas de error
No entre en pánico si ve el mensaje de error
ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client
. Surge porque en el mismo controlador se llama repetidamente al método que establece los encabezados de respuesta. Estos son los métodos que llaman para configurar automáticamente los encabezados de respuesta:
- enviar res.
- res.json
- res.render
- res.sendFile
- res.sendStatus
- res.end
- res.redirect
Entonces, por ejemplo, si llama a los
res.json
res.render
y
res.json
en el mismo manejador de respuestas, obtendrá el error
ERR_HTTP_HEADERS_SENT
:
app.get('/testing', (req, res) => { res.render('new-page') res.json({ message: '¯\_(ツ)_/¯' }) })
Como resultado, si encuentra este error, verifique cuidadosamente el código del controlador de respuestas y asegúrese de que no haya situaciones en las que se invoquen varios de los métodos descritos anteriormente.
▍ Manejo de errores y transmisión de datos
Si algo sale mal al transmitir la respuesta a la interfaz, entonces puede encontrar el mismo error
ERR_HTTP_HEADERS_SENT
.
En este caso, el manejo de errores debe pasarse a los manejadores estándar. Dicho controlador enviará un error y cerrará automáticamente la conexión.
app.use((error, req, res, next) => {
Resumen
Hoy les conté todo lo que sé sobre el manejo de errores en Express. Espero que esto te ayude a escribir aplicaciones Express más confiables.
Estimados lectores! ¿Cómo maneja los errores en sus proyectos Node.js?
