Volver a JavaScript Intermedio

Manejo de Errores y Depuración

Un manejo robusto de errores distingue el código listo para producción del código de hobby.

Tipos de Error

// Tipos de error integrados new Error('Error genérico'); new TypeError('Tipo incorrecto'); new RangeError('Fuera de rango'); new SyntaxError('Sintaxis inválida'); new ReferenceError('Variable no definida'); // Clases de error personalizadas class ErrorApp extends Error { constructor(mensaje, codigo, statusCode = 500) { super(mensaje); this.name = 'ErrorApp'; this.codigo = codigo; this.statusCode = statusCode; } } class ErrorNoEncontrado extends ErrorApp { constructor(recurso) { super(`${recurso} no encontrado`, 'NOT_FOUND', 404); this.name = 'ErrorNoEncontrado'; } } throw new ErrorNoEncontrado('Usuario'); // ErrorNoEncontrado: Usuario no encontrado

Try/Catch/Finally

async function cargarUsuario(id) { try { const response = await fetch(`/api/usuarios/${id}`); if (!response.ok) { if (response.status === 404) throw new ErrorNoEncontrado('Usuario'); throw new ErrorApp(`HTTP ${response.status}`, 'HTTP_ERROR', response.status); } return await response.json(); } catch (err) { if (err instanceof ErrorNoEncontrado) { // Manejar específicamente return null; } // Re-lanzar errores inesperados throw err; } finally { // Siempre se ejecuta — ideal para limpieza ocultarCargando(); } }

Manejo Global de Errores

// Capturar errores síncronos no manejados window.onerror = function (mensaje, fuente, linea, columna, error) { registrarErrorEnServicio({ mensaje, fuente, linea, error }); return true; // Evita el manejo por defecto del navegador }; // Capturar rechazos de promesas no manejados window.addEventListener('unhandledrejection', event => { registrarErrorEnServicio({ razón: event.reason }); event.preventDefault(); });

Patrón Result (Sin Excepciones)

Para flujos de error predecibles, retorna un objeto resultado en lugar de lanzar:

function dividir(a, b) { if (b === 0) return { ok: false, error: 'División por cero' }; return { ok: true, valor: a / b }; } const resultado = dividir(10, 0); if (!resultado.ok) { console.error(resultado.error); } else { console.log(resultado.valor); }

Técnicas de Depuración

// Más descriptivo que console.log console.group('Carga de usuario'); console.time('fetch'); const usuario = await obtenerUsuario(1); console.timeEnd('fetch'); // "fetch: 234ms" console.table(usuario); // Muestra en formato tabla console.groupEnd(); // Punto de interrupción condicional // En DevTools → pestaña Sources: clic derecho en breakpoint → Editar → añadir condición // Perfilado de rendimiento performance.mark('inicio-render'); renderizarListaCostosa(); performance.mark('fin-render'); performance.measure('render', 'inicio-render', 'fin-render'); const [medida] = performance.getEntriesByName('render'); console.log(`El render tardó ${medida.duration}ms`);

Patrón Error Boundary (Funcional)

const conManejoDeError = async (fn, fallback = null) => { try { return await fn(); } catch (err) { console.error('Capturado:', err); return fallback; } }; // Uso const usuarios = await conManejoDeError( () => fetch('/api/usuarios').then(r => r.json()), [] // Retorna array vacío ante fallos );