Manejo de errores en JavaScript: try/catch, async/await y patrones avanzados

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Manejo avanzado de errores en JavaScript: desde try/catch hasta interceptores globales

\n\n

El manejo de errores no es simplemente "envolver el código en try/catch". En aplicaciones reales de producción en Node.js, una gestión adecuada de excepciones permite evitar caídas del servidor, registrar problemas correctamente y proporcionar al usuario mensajes claros. En este artículo, exploraremos técnicas avanzadas de manejo de errores en JavaScript que van más allá de la sintaxis básica.

\n\n

1. Inmersión profunda en try/catch y finally

\n\n

La construcción clásica try...catch...finally sigue siendo la base del manejo síncrono. Sin embargo, a nivel avanzado es importante comprender los matices de su funcionamiento.

\n\n
function riskyOperation(value) {\n  if (typeof value !== 'number') {\n    throw new TypeError('El argumento debe ser un número');\n  }\n  if (value < 0) {\n    throw new RangeError('El valor no puede ser negativo');\n  }\n  return Math.sqrt(value);\n}\n\ntry {\n  const result = riskyOperation(-4);\n  console.log('Resultado:', result);\n} catch (error) {\n  if (error instanceof TypeError) {\n    console.error('Error de tipo:', error.message);\n  } else if (error instanceof RangeError) {\n    console.error('Error de rango:', error.message);\n  } else {\n    console.error('Error desconocido:', error);\n  }\n} finally {\n  console.log('Limpieza: siempre se ejecuta');\n}
\n\n

Puntos clave:

\n
    \n
  • El bloque finally siempre se ejecuta, incluso si hay un return en try o catch.
  • \n
  • Utilice las clases de error integradas (TypeError, RangeError, SyntaxError) para una identificación precisa.
  • \n
  • No capture errores que no pueda manejar; déjelos ascender.
  • \n
\n\n

2. Clases de error personalizadas y extensión de Error

\n\n

Para proyectos grandes, los tipos de error estándar no son suficientes. Crear clases propias permite agregar metadatos (código de estado HTTP, código de error, contexto) y simplifica el filtrado.

\n\n
class AppError extends Error {\n  constructor(message, statusCode, code) {\n    super(message);\n    this.name = 'AppError';\n    this.statusCode = statusCode;\n    this.code = code;\n    Error.captureStackTrace(this, this.constructor);\n  }\n}\n\nclass ValidationError extends AppError {\n  constructor(message, field) {\n    super(message, 400, 'VALIDATION_ERROR');\n    this.field = field;\n  }\n}\n\nclass DatabaseError extends AppError {\n  constructor(message, query) {\n    super(message, 500, 'DB_ERROR');\n    this.query = query;\n  }\n}\n\n// Uso\ntry {\n  throw new ValidationError('El correo electrónico es obligatorio', 'email');\n} catch (error) {\n  if (error instanceof ValidationError) {\n    console.log(`Campo: ${error.field}, Estado: ${error.statusCode}`);\n  }\n}
\n\n

Por qué es importante: los errores personalizados permiten manejar diferentes escenarios de forma centralizada (por ejemplo, en middleware de Express.js) y devolver un JSON estructurado al cliente.

\n\n

3. Manejo de errores en código asíncrono: async/await y Promise

\n\n

En Node.js, la mayor parte del código es asíncrono. Los errores en Promise y async/await requieren un enfoque especial.

\n\n

3.1. Manejo de Promise

\n\n
function fetchUserData(userId) {\n  return new Promise((resolve, reject) => {\n    if (userId <= 0) {\n      reject(new RangeError('ID de usuario no válido'));\n    }\n    // simulación de consulta a BD\n    setTimeout(() => resolve({ id: userId, name: 'Alice' }), 100);\n  });\n}\n\nfetchUserData(-1)\n  .then(user => console.log(user))\n  .catch(error => {\n    console.error('Promise rechazada:', error.message);\n  })\n  .finally(() => console.log('Limpieza después de la promesa'));
\n\n

3.2. Manejo de async/await

\n\n
async function getUserProfile(userId) {\n  try {\n    const user = await fetchUserData(userId);\n    const posts = await fetchUserPosts(user.id                

Blogs

Book Recommendations