Manejo de Errores con Async/Await en JavaScript

El uso de async y await en JavaScript hace que el código asíncrono sea más legible y fácil de entender. Sin embargo, un aspecto crucial para mantener un flujo de trabajo robusto es el manejo de errores en funciones asíncronas.

En este artículo exploraremos cómo capturar errores con try/catch, cómo utilizar finally y algunas prácticas avanzadas para asegurar que el código sea confiable.

Captura de Errores con try/catch en Funciones Asíncronas

Cuando trabajamos con async/await, los errores se pueden capturar directamente en un bloque try/catch, evitando el uso de .catch() en cada llamada a una promesa. Esto permite gestionar todos los errores de la función en una sola sección, facilitando la depuración.

Ejemplo Básico de Manejo de Errores con try/catch

async function obtenerDatos() {
  try {
    const respuesta = await fetch('https://api.example.com/datos');
    const datos = await respuesta.json();
    console.log("Datos recibidos:", datos);
  } catch (error) {
    console.error("Error al obtener datos:", error.message);
  }
}

obtenerDatos();

En el código anterior vemos que si ocurre algún error durante la solicitud HTTP o al convertir la respuesta a JSON, el bloque catch captura el error, permitiendo manejarlo sin detener el flujo general del programa.


Validación y Manejo de Errores Condicionales

Con async/await es común agregar validaciones en cada paso del proceso para asegurarse de que los datos o respuestas sean correctos antes de continuar. Esto permite manejar errores de manera condicional y específica.

Ejemplo: Validación de Respuesta

async function obtenerUsuario(id) {
  try {
    const respuesta = await fetch(`https://api.example.com/usuario/${id}`);
    if (!respuesta.ok) {
      throw new Error("Usuario no encontrado");
    }
    const usuario = await respuesta.json();
    console.log("Datos del usuario:", usuario);
  } catch (error) {
    console.error("Error al obtener usuario:", error.message);
  }
}

obtenerUsuario(5);

En este ejemplo se valida que la respuesta HTTP sea satisfactoria antes de intentar convertirla a JSON. Si la respuesta no es correcta (ok es false), el flujo lanza un error personalizado.


Ejecución Final con finally en Funciones Asíncronas

finally es una sección que se ejecuta después de try/catch, independientemente de si hubo un error o no. Esto es útil para realizar tareas de limpieza o finalizar acciones sin importar el resultado.

async function procesarArchivo() {
  try {
    const archivo = await abrirArchivo('archivo.txt');
    console.log("Archivo procesado:", archivo);
  } catch (error) {
    console.error("Error al procesar archivo:", error.message);
  } finally {
    console.log("Liberando recursos...");
    cerrarArchivo();
  }
}

procesarArchivo();
"Error al procesar archivo:"
"Liberando recursos..."

En este caso, el bloque finally asegura que el archivo se cierre, independientemente de si la operación fue exitosa o fallida.


Uso de Funciones Auxiliares para Captura de Errores

Encapsular el manejo de errores en funciones auxiliares facilita la reutilización y reduce la repetición de código, especialmente cuando manejamos varias promesas en paralelo o en secuencia.

Ejemplo de Función Auxiliar para Manejo de Errores

async function manejarErrores(funcion) {
  try {
    return await funcion();
  } catch (error) {
    console.error("Error capturado:", error.message);
    return null;
  }
}

async function obtenerDatos() {
  return await manejarErrores(async () => {
    let respuesta = await fetch('https://api.example.com/datos');
    return await respuesta.json();
  });
}

obtenerDatos().then(datos => console.log(datos));

En el código anterior la función asíncrona manejarErrores encapsula el bloque try/catch, centralizando el manejo de errores. Esto es útil para evitar múltiples bloques try/catch en el código.


Manejo de Errores en Funciones Paralelas con Promise.all y async/await

Cuando se realizan múltiples operaciones en paralelo con Promise.all, es esencial capturar los errores correctamente para asegurarse de que el flujo no se interrumpa si una de las promesas falla.

Ejemplo de Manejo de Errores en Promesas Paralelas

async function obtenerDatosParalelo() {
  try {
    let [usuario, pedidos] = await Promise.all([
      fetch('https://api.example.com/usuario/1').then(res => res.json()),
      fetch('https://api.example.com/pedidos/1').then(res => res.json())
    ]);
  
    console.log("Datos del usuario:", usuario);
    console.log("Datos de pedidos:", pedidos);
  } catch (error) {
    console.error("Error en las operaciones paralelas:", error.message);
  }
}

obtenerDatosParalelo();

En este ejemplo, si una de las promesas falla, el catch captura el error y evita que el flujo de ejecución falle por completo.


Buenas Prácticas para Manejo de Errores con async/await

Implementar buenas prácticas en el manejo de errores con async/await ayuda a mantener el código más seguro y fácil de depurar.

  1. Centraliza la Captura de Errores con Funciones Auxiliares: Crear funciones que encapsulen bloques try/catch permite un manejo de errores más limpio y reutilizable.
  2. Utiliza finally para Liberación de Recursos: Asegúrate de utilizar finally para liberar recursos como archivos, conexiones de red o memoria, sin importar el resultado de la operación.
  3. Maneja Errores Específicos con Validaciones Condicionales: Agrega verificaciones y errores personalizados en funciones para capturar errores específicos y mejorar la comprensión del flujo.

Conclusión

El manejo de errores en funciones async/await es fundamental para escribir código asíncrono robusto y seguro. Al capturar errores con try/catch, utilizar finally para limpieza y adoptar prácticas como encapsular bloques de captura en funciones, puedes asegurar que el código sea menos propenso a fallos inesperados. Estas prácticas mejoran la legibilidad y la confiabilidad de las aplicaciones asíncronas.

+1
0
+1
0