Introducción al Error UnhandledPromiseRejection en Node.js
Cuando desarrollamos aplicaciones backend utilizando Node.js, es muy común trabajar con operaciones asíncronas basadas en promesas o funciones async/await. Sin embargo, si una promesa es rechazada y no se proporciona un mecanismo adecuado para capturar ese error, Node.js lanzará una advertencia o un error crítico conocido como UnhandledPromiseRejection. En las versiones modernas de Node.js, esto puede incluso terminar crasheando la aplicación por completo, afectando la disponibilidad del servicio.
Causas Principales de las Promesas No Manejadas
El origen de este problema se debe principalmente a fallas en el manejo de excepciones asíncronas en el código. Las causas más frecuentes incluyen:
- Omitir el bloque
try...catchal utilizar funcionesasync/await. - Olvidar encadenar el método
.catch()al final de una promesa tradicional. - Errores en conexiones a bases de datos o peticiones HTTP externas que fallan silenciosamente.
Método 1: Implementar Try-Catch en Funciones Async/Await
La forma más limpia y recomendada de evitar este error al usar la sintaxis moderna es envolver el código propenso a fallos dentro de una estructura try...catch.
Ejemplo incorrecto:
const obtenerDatos = async () => { const datos = await api.getData(); console.log(datos); };Ejemplo corregido paso a paso:
- Identifica la función asíncrona que realiza operaciones críticas.
- Añade la palabra reservada
tryantes del bloque de ejecución. - Implementa el bloque
catch (error)para gestionar la excepción adecuadamente.
const obtenerDatosSeguro = async () => { try { const datos = await api.getData(); console.log(datos); } catch (error) { console.error('Error al obtener los datos:', error.message); } };Método 2: Capturar Promesas con .catch()
Si prefieres utilizar la sintaxis basada en promesas sin async/await, debes asegurarte de terminar siempre la cadena de ejecución con el método correspondiente.
- Localiza la llamada que devuelve una promesa (por ejemplo, consultas a Mongoose o Axios).
- Añade
.catch()al final de la sentencia.
api.getData() .then(datos => console.log(datos)) .catch(error => console.error('Promesa rechazada capturada:', error));Método 3: Manejador Global para Emergencias (Fallback)
Para evitar que tu aplicación Node.js colapse inesperadamente ante cualquier promesa no controlada en terceros o módulos externos, puedes registrar un listener global a nivel de proceso.
Añade el siguiente código al inicio de tu archivo principal (como index.js o app.js):
process.on('unhandledRejection', (reason, promise) => { console.error('Promesa no manejada detectada:', promise, 'Motivo:', reason); // Opcional: realizar limpieza y cerrar el servidor de forma controlada process.exit(1); });