W3docs

Manejo de errores try…catch en JavaScript

Aprende el manejo de errores en JavaScript con try, catch, finally y throw. Cubre el objeto Error, tipos integrados, vinculación opcional, relanzamiento y limitaciones asíncronas.

Dominar el manejo de errores en JavaScript con Try...Catch

Manejar errores de forma eficaz es fundamental para crear aplicaciones robustas en JavaScript. Cuando algo falla en tiempo de ejecución — una llamada de red falla, un JSON está mal formado, una variable es undefined — JavaScript lanza una excepción. Sin un manejo adecuado, esa excepción detiene el script. Este artículo cubre la sentencia try...catch, la cláusula finally, el operador throw, el objeto Error y sus subtipos integrados, el relanzamiento de errores, y la limitación importante de que try...catch sincrónico no puede capturar errores lanzados dentro de callbacks asíncronos.

Entender Try...Catch en JavaScript

La sentencia try...catch es una herramienta para gestionar excepciones — errores que ocurren durante la ejecución del programa. Permite manejar estas excepciones de forma controlada en lugar de dejar que bloqueen todo el script.

El mecanismo tiene dos bloques:

  • try — el código que podría lanzar un error. JavaScript lo ejecuta normalmente.
  • catch (error) — se ejecuta solo si algo en el bloque try lanza un error. El valor lanzado se pasa como error.

Si no ocurre ningún error, el bloque catch se omite por completo. Si ocurre un error, la ejecución salta inmediatamente a catch — el resto del bloque try no se ejecuta.

Sintaxis básica de Try...Catch

A continuación se muestra un ejemplo sencillo para ilustrar la estructura básica de try...catch:


javascript— editable

En este ejemplo, cualquier error que ocurra dentro del bloque try es capturado por el bloque catch, donde puede manejarse sin que el script se detenga.

Lanzar tus propios errores con throw

El operador throw genera una excepción. Puedes lanzar cualquier valor, pero la convención — y lo único que debes hacer en la práctica — es lanzar un objeto Error (o una instancia de alguno de sus subtipos). Hacerlo te proporciona automáticamente un message útil y un rastro de pila (stack).

javascript— editable

Evita throw 'a string' o throw 42. Una cadena lanzada no tiene message, ni name, ni stack, por lo que el código que espera un objeto Error (como hace la mayoría) se comportará incorrectamente. Para errores específicos del dominio con campos adicionales, define tu propia clase — consulta errores personalizados, extender Error.

El objeto Error

Cuando haces new Error(message), obtienes un objeto con tres propiedades de uso común:

  • name — el tipo de error, por ejemplo "Error", "TypeError", "SyntaxError".
  • message — la descripción legible que pasaste al constructor.
  • stack — una cadena con la pila de llamadas en el momento en que se creó el error (no estándar pero compatible con todos los motores principales; muy útil para depurar, no para controlar el flujo).
javascript— editable

Tipos de errores integrados

JavaScript incluye varias subclases de Error que el motor lanza automáticamente. Conocerlas te ayuda a escribir lógica de catch más precisa:

TipoSe lanza cuando
SyntaxErrorEl código o los datos están mal formados, por ejemplo JSON.parse() con JSON inválido.
TypeErrorUn valor no es del tipo esperado, por ejemplo al llamar a algo que no es una función o al leer una propiedad de undefined.
ReferenceErrorSe hace referencia a una variable que no existe.
RangeErrorUn valor está fuera de su rango permitido, por ejemplo una longitud de array inválida.
URIErrordecodeURIComponent() o similar recibe un URI malformado.
EvalErrorHistórico; raramente lanzado por los motores modernos.

Cada uno tiene name establecido en su tipo, por lo que puedes bifurcar con instanceof:

javascript— editable

Manejar errores específicos

También puedes manejar tipos específicos de errores examinando el objeto de error:


javascript— editable

Este ejemplo maneja específicamente el SyntaxError que puede ocurrir durante el análisis de JSON. Si el error capturado es una instancia de SyntaxError, se gestiona registrando un mensaje específico. Si no lo es, el error se relanza, posiblemente para ser capturado por un manejador de errores de nivel superior o para detener el programa, indicando un escenario de error no manejado.

Relanzar errores

Un bloque catch captura todos los errores de su try, incluyendo aquellos que no sabes cómo manejar. El patrón recomendado es: inspeccionar el error, manejar los casos que conoces y relanzar todo lo demás para que se propague a un manejador externo. Silenciar errores desconocidos oculta bugs reales.

javascript— editable

Vinculación opcional de catch

Si no necesitas el valor del error, puedes omitir el enlace por completo (ES2019+). Esto es útil cuando solo te importa el hecho de que algo falló:

javascript— editable

Usar Finally

La cláusula finally se ejecuta después de los bloques try y catch, independientemente de si se lanzó o capturó una excepción. Es útil para liberar recursos o realizar tareas de limpieza, sin importar el resultado del try...catch:


javascript— editable

Esto garantiza que el mensaje "Finally block executed" se registre tanto si ocurre un error como si no, demostrando cómo finally puede usarse para realizar las acciones de limpieza necesarias.

Ejemplos reales con la API

Usar la API JSONPlaceholder es una forma excelente de practicar el manejo de datos reales en JavaScript, especialmente al trabajar con peticiones asíncronas y gestionar posibles errores que puedan surgir durante estas operaciones. A continuación se presentan algunos ejemplos del mundo real usando la API JSONPlaceholder, que ofrece datos REST falsos en línea con los que puedes experimentar para pruebas y prototipos.

Ejemplo 1: Obtener publicaciones y manejar errores

En este ejemplo, obtenemos publicaciones de la API JSONPlaceholder usando fetch y manejamos posibles errores de red o problemas con la respuesta de la API:


javascript— editable

Este script realiza una petición HTTP para recuperar un único elemento todo. Comprueba si la respuesta es exitosa (es decir, estado HTTP 200-299). Si no lo es, lanza un error con el estado de la respuesta. Cualquier error, ya sea por problemas de red o por la sentencia throw, es capturado en el bloque catch y registrado. El bloque finally se ejecuta independientemente del resultado, asegurando que se realicen las operaciones de limpieza o finales necesarias.

Ejemplo 2: Enviar datos y manejar excepciones

Aquí mostramos cómo enviar datos al servidor usando el método POST y manejar las excepciones de forma adecuada:


javascript— editable

En este script, enviamos una nueva publicación al servidor. La función fetch se usa con el método POST, incluyendo cabeceras y un cuerpo serializado como JSON. Si la respuesta del servidor indica un fallo (estado HTTP no 2xx), se lanza un error que luego es capturado y manejado en el bloque catch. Independientemente del éxito o fallo, el bloque finally garantiza que la operación quede marcada como completada.

Ejemplo 3: Provocar y manejar un error deliberadamente

Este ejemplo solicita intencionadamente un ID de usuario que no existe en la API JSONPlaceholder, lo que provoca un error 404 Not Found que capturaremos y manejaremos.


javascript— editable

Cómo funciona este ejemplo

  1. Endpoint de API inválido: Se llama a la función fetch con una URL que incluye un ID de usuario inválido (99999). Dado que JSONPlaceholder normalmente no tiene un usuario en ese índice, la API devolverá un error 404.
  2. Verificar la validez de la respuesta: El código comprueba si el estado de la respuesta no está en el rango de éxito (200-299). Como el ID de usuario es inválido, la respuesta de la API será probablemente 404, activando el manejo de errores en la comprobación if (!response.ok).
  3. Lanzamiento del error: Dado que la respuesta no es correcta, se lanza un error con un mensaje que incluye el estado HTTP, que en este caso indicará un error 404 Not Found.
  4. Bloque catch: El bloque catch captura el error lanzado y registra un mensaje específico usando console.log. Esto proporciona información clara sobre qué salió mal.
  5. Bloque finally: Este bloque se usa para limpieza o sentencias finales, indicando la finalización del intento independientemente del resultado.

Por qué Try...Catch no puede capturar errores de callbacks asíncronos

Este es el error más común con try...catch. La sentencia es síncrona: solo captura errores lanzados mientras el bloque try se está ejecutando actualmente. Cuando programas un callback con setTimeout, un escuchador de eventos, o una promesa sin await, el callback se ejecuta más tarde — después de que try...catch ya ha terminado y la pila de llamadas está vacía. En ese momento no hay ningún try circundante que pueda capturar nada.

javascript— editable

Para manejar el error, el try...catch debe estar dentro del callback, donde el error realmente se lanza:

javascript— editable

La misma regla explica por qué try...catch funciona con async/await pero no con promesas sin await. await pausa la función y la reanuda en el mismo flujo lógico, por lo que una promesa rechazada aparece como un error lanzado que tu try puede capturar. Una promesa que no usas con await se resuelve de forma independiente y elude el try circundante — en ese caso debes usar .catch().

javascript— editable

Para una cobertura más detallada del manejo asíncrono de errores, consulta Manejo de errores con promesas y async/await.

Conclusión

El manejo eficaz de errores en JavaScript es clave para desarrollar aplicaciones de alta calidad y resilientes. Usar try...catch te permite gestionar de forma controlada los errores síncronos y los rechazos con await, manteniendo el control sobre el flujo de la aplicación. Lanza objetos Error (nunca cadenas simples), bifurca sobre tipos integrados como TypeError y SyntaxError, relanza lo que no puedes manejar, y recuerda la limitación asíncrona: los errores en callbacks y promesas sin await necesitan su propio manejo.

Temas relacionados

Práctica

Práctica
¿Cuál es el propósito de la sentencia try/catch en JavaScript?
¿Cuál es el propósito de la sentencia try/catch en JavaScript?
Was this page helpful?