Command Palette

Search for a command to run...

Global Error Handling: Captura Excepciones No Controladas

Aprende a configurar manejadores globales de errores para capturar excepciones no controladas en toda tu aplicación JavaScript.

Lectura: 12 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • window.onerror captura errores de runtime en JavaScript síncrono
  • addEventListener('error') captura errores de recursos y eventos
  • unhandledrejection captura promesas rechazadas sin catch
  • Los manejadores globales NO detienen la ejecución del programa
  • Usa estos handlers para logging y reporting, no para lógica de negocio

Introducción al Manejo Global de Errores

El manejo global de errores en JavaScript es una técnica fundamental para aplicaciones en producción. Cuando un error ocurre fuera de un bloque try-catch, JavaScript busca manejadores globales que puedan capturar la excepción. Sin estos manejadores, los errores no controlados pueden dejar la aplicación en un estado inconsistente y, peor aún, pueden pasar desapercibidos en entornos de producción.

Los manejadores globales de errores te permiten centralizar el logging, enviar errores a servicios de monitoreo, y proporcionar una mejor experiencia de usuario mostrando mensajes amigables en lugar de que la aplicación se rompa silenciosamente. Sin embargo, es importante entender que estos mecanismos tienen limitaciones y no deben reemplazar el manejo de errores local con try-catch.

Manejadores globales vs try-catch

Los manejadores globales son un "safety net" para errores que escapan de tu código. No los uses como reemplazo de try-catch local. Siempre intenta capturar errores cerca de donde ocurren, usando los manejadores globales como último recurso.

  • Capturar errores que escapan de bloques try-catch
  • Centralizar el logging de errores para debugging
  • Enviar errores a servicios de monitoreo como Sentry
  • Proporcionar feedback al usuario cuando algo falla
  • Prevenir que errores silenciosos pasen desapercibidos

window.onerror: El Primer Manejador Global

window.onerror es el mecanismo más antiguo y básico para capturar errores globales en JavaScript. Este evento se dispara cuando ocurre un error de runtime en JavaScript síncrono que no es capturado por ningún bloque try-catch. El manejador recibe cinco argumentos que te dan información detallada sobre el error: el mensaje de error, la URL del archivo, el número de línea, el número de columna y el objeto Error.

Uso Básico de window.onerror

Para configurar un manejador global de errores, simplemente asignas una función a window.onerror. Esta función debe devolver true si quieres prevenir que el error se propague al manejador por defecto del navegador, o false para permitir que el navegador muestre su consola de errores.

onerror-basico.js
Loading code...

Este ejemplo muestra cómo configurar window.onerror para capturar errores globales. El manejador recibe información detallada sobre el error incluyendo el mensaje, la URL del archivo, y la línea donde ocurrió. Devolver true evita que el error se muestre en la consola del navegador, lo cual es útil en producción pero no recomendado durante el desarrollo.

Limitaciones de window.onerror

window.onerror NO captura errores en código asíncrono como setTimeout, setInterval, ni captura errores de carga de recursos (imágenes, scripts). Para esos casos necesitas usar addEventListener('error') y unhandledrejection.

Logging Avanzado con window.onerror

En una aplicación real, querrás hacer más que simplemente console.log los errores. Un patrón común es enviar la información del error a un servidor de logging o servicio de monitoreo. Esto te permite rastrear errores en producción y tener visibilidad de problemas que afectan a tus usuarios.

onerror-logging.js
Loading code...

Este ejemplo implementa un sistema de logging más robusto que envía errores a un servidor ficticio. La función de logging incluye información contextual como la URL actual, el user agent del navegador, y un timestamp. En producción, esto te permite tener un registro completo de errores para debugging y análisis de patrones.

addEventListener('error'): Captura de Errores de Recursos

Mientras que window.onerror captura errores de JavaScript, addEventListener('error') en window captura un tipo diferente de error: errores de carga de recursos. Esto incluye errores al cargar imágenes, scripts, hojas de estilo, y otros recursos externos. Este evento también captura algunos errores de JavaScript que window.onerror no puede manejar, como errores en código ejecutado desde setTimeout o setInterval.

Capturando Errores de Carga de Recursos

Los errores de carga de recursos son comunes en aplicaciones web modernas que dependen de múltiples activos externos. Una imagen que no carga, un script que falla, o una hoja de estilo bloqueada pueden afectar seriamente la experiencia del usuario. Capturar estos errores te permite manejarlos graciosamente, por ejemplo, mostrando una imagen de respaldo o registrando el problema.

error-recursos.js
Loading code...

Este ejemplo muestra cómo capturar errores de carga de recursos. El evento error tiene propiedades específicas para recursos: target indica qué elemento falló, y el evento puede ser prevenido con preventDefault(). Es importante notar que este evento también captura errores de JavaScript en ciertos contextos asíncronos.

Diferencia clave con window.onerror

addEventListener('error') captura errores de recursos y algunos errores asíncronos, mientras que window.onerror captura errores de JavaScript síncrono. En aplicaciones modernas, es recomendable usar ambos para cubrir todos los casos.

Capturando Errores en setTimeout y setInterval

Los errores que ocurren dentro de callbacks de setTimeout y setInterval no son capturados por window.onerror tradicionalmente. Sin embargo, addEventListener('error') puede capturar algunos de estos errores dependiendo del navegador. Es importante entender estas limitaciones y manejar explícitamente los errores en código asíncrono.

error-async.js
Loading code...

Este ejemplo demuestra la diferencia entre window.onerror y addEventListener('error') al capturar errores en código asíncrono. Como puedes ver, addEventListener('error') es más efectivo para capturar errores en setTimeout, aunque la mejor práctica sigue siendo manejar explícitamente los errores dentro de tus callbacks asíncronos.

unhandledrejection: Capturando Promesas Rechazadas

Con la introducción de promesas en JavaScript, surgió un nuevo tipo de error: promesas rechazadas que nunca tienen un bloque catch para manejarlas. Estos "unhandled rejections" pueden causar problemas difíciles de debuggear porque el error ocurre de forma asíncrona y no hay stack trace directo. El evento unhandledrejection te permite capturar estos errores y manejarlos apropiadamente.

Capturando Promesas Rechazadas

El evento unhandledrejection se dispara cuando una promesa es rechazada y no hay ningún handler catch para manejarla en el mismo microtask. El evento contiene una propiedad reason que es el valor con el que fue rechazada la promesa. Este mecanismo es crucial para aplicaciones que usan mucho async/await o promesas.

unhandledrejection-basico.js
Loading code...

Este ejemplo muestra cómo capturar promesas rechazadas que no tienen un handler. El evento unhandledrejection te da acceso a la razón del rechazo a través de event.reason. Es importante notar que este evento solo se dispara para promesas que no tienen un catch en el mismo ciclo de eventos.

PreventDefault en unhandledrejection

Si llamas a event.preventDefault() en el handler de unhandledrejection, previenes que el navegador muestre un warning en la consola. Esto es útil en producción pero ten cuidado: en desarrollo, estos warnings son valiosos para detectar promesas no manejadas.

Unhandled Rejections con async/await

El uso de async/await puede hacer que sea más fácil olvidarse de manejar rechazos de promesas. Cuando usas await sin try-catch, cualquier rechazo de la promesa resultará en un unhandled rejection. Es crucial entender este patrón y asegurarte de que todas las funciones async tengan manejo de errores apropiado.

unhandledrejection-async-await.js
Loading code...

Este ejemplo muestra cómo async/await puede generar unhandled rejections si no se manejan correctamente. La función processDataAsyncSinCatch demuestra el problema: si la promesa se rechaza, no hay try-catch para capturarlo. La función processDataAsyncConCatch muestra la solución correcta con try-catch.

Errores Comunes en Manejo Global de Errores

Al implementar manejo global de errores, es fácil cometer errores que pueden hacer que tu aplicación sea menos estable o más difícil de debuggear. Estos son los problemas más frecuentes que encontrarás y cómo evitarlos.

No Usar preventDefault()

Un error común es no llamar a preventDefault() en los manejadores de error, lo que puede resultar en que el navegador muestre múltiples mensajes de error o que el error se propague de forma inesperada. Esto es especialmente problemático en producción donde no quieres que los usuarios vean errores técnicos.

error-no-prevent-default.js
Loading code...

Este ejemplo muestra la diferencia entre usar y no usar preventDefault(). Sin preventDefault(), el navegador puede mostrar mensajes de error adicionales o comportarse de forma inesperada. Con preventDefault(), tienes control completo sobre cómo se maneja el error.

Reemplazar Manejadores Existentes

Otro error común es asignar directamente a window.onerror, lo cual reemplaza cualquier manejador existente que pueda haber configurado otra librería o framework. Esto puede causar que errores importantes no sean capturados por sistemas de monitoreo o logging que dependen de estos manejadores.

error-reemplazar-manipuladores.js
Loading code...

Este ejemplo muestra el problema de reemplazar manejadores existentes. La solución correcta es usar addEventListener() en lugar de asignar directamente a window.onerror. Esto permite que múltiples handlers coexistan y que todos puedan capturar errores.

Mejor práctica: addEventListener

Siempre usa addEventListener('error', handler) en lugar de window.onerror = handler. Esto permite que múltiples handlers coexistan y evita conflictos con otras librerías que también necesitan capturar errores globales.

Depender Exclusivamente de Manejadores Globales

El error más peligroso es depender exclusivamente de los manejadores globales de errores y no usar try-catch local. Los manejadores globales son un "safety net", no una solución principal. El manejo local de errores es más preciso, te permite manejar errores de forma específica según el contexto, y hace el código más mantenible.

error-dependencia-manipuladores.js
Loading code...

Este ejemplo muestra la diferencia entre depender de manejadores globales versus usar try-catch local. La función malaPractica depende exclusivamente de window.onerror, lo cual es frágil y difícil de mantener. La funcionBuenaPractica usa try-catch local para manejar errores de forma específica.

Resumen: Global Error Handling

Conceptos principales:

  • window.onerror captura errores de JavaScript síncrono
  • addEventListener('error') captura errores de recursos y algunos asíncronos
  • unhandledrejection captura promesas rechazadas sin catch
  • Los manejadores globales NO detienen la ejecución del programa
  • addEventListener permite múltiples handlers coexistir

Mejores prácticas:

  • Usa try-catch local como primera opción
  • Usa manejadores globales como safety net para errores no controlados
  • Implementa logging y reporting en manejadores globales
  • Usa addEventListener en lugar de asignar directamente a window.onerror
  • Llama a preventDefault() para prevenir comportamiento por defecto del navegador