CodeForge

JavaScript de Cero a Experto / Manejo de errores y debugging

throw, try, catch, finally: la red de seguridad

Teoría20 min20 XP

En el módulo 10 usaste try/catch para atrapar promesas que fallaban. Hoy lo ves completo y síncrono: cómo LANZAR un error a propósito cuando algo no cuadra, cómo atraparlo sin que el programa muera, y qué hace ese finally que siempre corre pase lo que pase.

El trapecista y la red

throw: levantar la mano

throw interrumpe el flujo en seco y "lanza hacia arriba" un valor —por convención, un objeto Error. Nada después del throw, dentro de esa función, se ejecuta:

Dos cosas cruciales: la línea después del dividir(10, 0) no se ejecutathrow corta el flujo ahí mismo—, y aun así el programa sobrevive porque el catch recibió el golpe. Siempre lanza objetos Error (throw new Error(...)), no strings sueltos: un Error trae name, stack y todo el parte del accidente de la lección 1. throw "texto" funciona, pero te roba esa información.

finally: el que corre pase lo que pase

El bloque finally se ejecuta SIEMPRE: si todo salió bien, si hubo error, incluso si hiciste return dentro del try. Es el lugar para lo que no puede quedarse a medias —cerrar, limpiar, apagar un spinner de carga:

Mira cómo "cerrando recurso" aparece en AMBOS casos —el exitoso y el fallido— incluso habiendo un return en el try y otro en el catch. Esa es la promesa de finally: lo que pongas ahí corre sí o sí. Su uso real favorito lo conociste en el módulo 10: apagar el estado "cargando..." de una petición, ya sea que llegue la respuesta o que falle.

El pecado capital: el catch vacío

La trampa que ya conoces: lo asíncrono

Un try/catch síncrono no atrapa un error que ocurre "más tarde", dentro de un setTimeout o una promesa sin await. Para cuando el error llega, el try ya terminó hace rato —su red se guardó. Míralo con el orden de los mensajes:

Fíjate en el orden de impresión (1 → 2 → 3): el console.log de afuera corre ANTES que el timeout, prueba de que el try ya cerró cuando el callback arranca. Por eso el catch de afuera es inútil para lo asíncrono, y la red tiene que ir DENTRO del callback. En código async moderno usas async/await con try/catch (módulo 10): el await "trae" el error de vuelta al try. Regla mental: un try/catch solo cubre lo que pasa DENTRO de él, AHORA. Lo que se agenda para después necesita su propia red.

Una función tiene un return dentro del try y también un bloque finally. Si el try hace return 'A', ¿corre el finally?

Mini-reto

Construye una red completa: 1) escribe raizSegura(n) que haga throw si n es negativo ("No hay raíz real de un negativo") y devuelva Math.sqrt(n) si no; 2) llámala dentro de un try/catch/finally con -9 y con 16, imprimiendo en el finally "cálculo terminado" en ambos casos; 3) comprueba que el finally corre las dos veces y que el programa no muere con el -9.

Qué sigue

Ya lanzas y atrapas errores genéricos. Pero un new Error("algo falló") es pobre: no distingue un valor inválido de una falla de red. En la siguiente lección creas tus PROPIOS tipos de error —con nombre y datos extra— usando las clases del módulo 11. Cumplimos una promesa que quedó pendiente.