Resumen

Dominar el manejo de errores con async await es fundamental para escribir código asíncrono robusto en JavaScript. Cuando una promesa falla y no existe un mecanismo de captura, la aplicación puede romperse sin ofrecer información útil para depurar el problema. Aquí se explica cómo try catch resuelve esto de forma clara y legible.

¿Por qué try catch reemplaza a catch en promesas?

Con el patrón de promesas tradicional, los errores se capturan encadenando .catch() al final de la cadena .then(). Sin embargo, cuando usamos await dentro de una función async, el mecanismo cambia: envolvemos el código que puede fallar dentro de un bloque try, y definimos un bloque catch para manejar cualquier excepción [0:42].

Sin try catch, si una promesa rechaza al usar await, se dispara un uncaught exception que no es fácil de entender ni de corregir. Al envolver el código, obtenemos mensajes claros como "Error al cargar usuario: fetch failed", lo que permite identificar rápidamente que la URL de la API está mal escrita o que el servicio no responde [1:15].

¿Cómo funciona un solo try catch para múltiples awaits?

Un solo bloque try catch protege todas las operaciones asíncronas que estén dentro de él. Esto es exactamente equivalente a cómo un .catch() protegía toda la cadena de promesas. Dentro del try puedes tener varios await consecutivos y, si cualquiera de ellos falla, el flujo salta directamente al catch [1:45].

¿Qué papel cumple finally en async await?

El combinador finally funciona igual que en las promesas: siempre se ejecuta, sin importar si la operación fue exitosa o si ocurrió un error [2:07]. Un caso de uso típico es ocultar un spinner de carga. Dentro del try se hace el fetch y se renderiza el perfil; en el catch se muestra el error; y en el finally se oculta el spinner, garantizando que la interfaz quede en un estado consistente.

¿Cuáles son los tres errores más comunes con async await?

Existen tres errores frecuentes que conviene memorizar [2:30]:

  • Olvidar usar await. Se escribe la función como async pero no se coloca await antes de la promesa, lo que hace que se trabaje con el objeto promesa en lugar de su valor resuelto.
  • No envolver el código en try catch. A veces se escribe el try pero se omite el catch, dejando los errores sin capturar.
  • Pensar que await captura errores automáticamente. Sin el bloque catch, los errores simplemente se propagan sin control.

Otro punto crítico: try catch solo captura errores dentro de su bloque. Si llamas a una función async sin await, el error no será atrapado por ese catch.

¿Cómo crear errores personalizados con throw new Error?

Dentro de un try, puedes lanzar errores con throw para representar condiciones que no son excepciones técnicas, como una respuesta HTTP con estatus 401 o 500 [3:18]. Esto es necesario porque fetch no rechaza la promesa ante errores HTTP; solo rechaza cuando hay un fallo de red.

javascript async function obtenerProducto(id) { try { const response = await fetch(https://api.escuelajs.co/api/v1/products/${id}); if (!response.ok) { throw new Error(Producto no encontrado, status: ${response.status}); } const producto = await response.json(); if (!producto || !producto.id) { throw new Error('Producto inválido o sin datos'); } console.log(producto.title); return producto; } catch (error) { console.error(error.message); } }

Al llamar con un ID válido como 3, se obtiene el título del producto. Al llamar con un ID inexistente como 999, se muestra el error personalizado [4:10].

¿Cuándo usar múltiples bloques try catch?

Cuando necesitas manejar errores distintos de forma distinta, separar los bloques tiene sentido [4:40]. Por ejemplo, al procesar un pedido:

  • El primer try catch obtiene el usuario. Si falla, es un error crítico que detiene la ejecución con throw.
  • El segundo try catch obtiene el inventario. Si falla, se usa un valor por defecto del caché y la aplicación continúa con un console.warn.

¿Cómo se compara promesas con catch frente a async await con try catch?

La versión con promesas encadena .then(), .catch() y .finally(). La versión con async await logra exactamente lo mismo, pero se lee de arriba abajo sin funciones anidadas [5:35]:

javascript async function cargarCategorias() { try { const response = await fetch('https://api.example.com/categories'); const datos = await response.json(); renderizar(datos); } catch (error) { mostrarError(error); } finally { ocultarSpinner(); } }

El bloque try catch con async await unifica el manejo de errores síncronos y asíncronos en un solo patrón. Ya no hay diferencia conceptual entre capturar un error de una operación normal y capturar el rechazo de una promesa.

¿Has tenido algún caso donde necesitaste múltiples bloques try catch? Comparte tu experiencia en los comentarios.