Resumen

Dominar la conversión entre promesas y async await es una habilidad fundamental para cualquier desarrollador JavaScript. Conocer el patrón de traducción permite leer código legado con .then y reescribirlo con una sintaxis más clara, sin modificar el comportamiento. Aquí se explican las reglas base y se aplican a ejemplos reales con distintos niveles de complejidad.

¿Cuáles son las reglas base para convertir promesas a async await?

El proceso de conversión sigue un patrón predecible y consistente [0:18]:

  • Cada .then se convierte en un await en una nueva línea.
  • El valor que antes llegaba como argumento del callback ahora se asigna directamente a una variable.
  • El .catch se transforma en un bloque try catch.
  • La función que contiene los await debe marcarse con la palabra clave async.

Este patrón aplica sin importar cuántos .then encadenados existan. La lógica interna permanece idéntica; lo que cambia es únicamente la sintaxis.

¿Cómo se refactoriza una cadena simple de promesas?

En el primer ejemplo se trabaja con una función que obtiene un título desde una API como JSON Placeholder [1:00]. Con promesas, la estructura incluye dos .then encadenados: el primero convierte la respuesta a JSON y el segundo transforma el título a letra mayúscula. Al final, un .catch captura posibles errores.

Con async await, la función se marca como async y cada paso se expresa de forma secuencial:

  • Se usa await fetch(url) para obtener la respuesta.
  • Se usa await response.json() para parsear el JSON.
  • Se transforma el título a mayúscula directamente.
  • Todo se envuelve en un bloque try catch para manejar errores.

El resultado es código que se lee de arriba hacia abajo, como una secuencia de instrucciones lineales.

¿Qué pasa con cadenas que tienen dependencias entre sí?

El segundo ejemplo presenta un caso más complejo: cargar un perfil de usuario donde cada paso depende del anterior [1:51]. Con promesas, se encadenan tres .then junto con .catch y .finally:

  • Primero se obtiene el usuario y se renderizan sus datos.
  • Con ese usuario se obtienen sus posts.
  • Con esos posts se obtienen los comentarios.
  • Si ocurre un error, se captura en .catch.
  • En .finally se oculta el spinner de carga.

Con async await, la función asíncrona utiliza tres bloques: try, catch y finally [2:29]. Dentro del try, cada operación se asigna a una variable con await, haciendo explícita la dependencia entre pasos. El código resultante es mucho más legible y fácil de seguir que las promesas anidadas.

¿Cómo se convierte un Promise.all a async await?

El tercer ejemplo aborda la ejecución paralela con Promise.all [3:03]. Cuando varias promesas deben resolverse simultáneamente —como obtener usuario, notificaciones y configuración— se agrupan en un Promise.all. Con promesas, el resultado llega en un .then y los errores en .catch.

Al refactorizar con async await:

  • Se usa await Promise.all([...]) para esperar todas las promesas en paralelo.
  • Los resultados se desestructuran directamente en variables.
  • El manejo de errores se realiza con try catch.

Es importante notar que Promise.all sigue siendo necesario dentro de async await cuando se requiere ejecución paralela en lugar de secuencial.

¿Siempre conviene usar async await sobre promesas?

No siempre. Para cadenas muy cortas y simples, el .then puede ser perfectamente claro y no hay razón para cambiarlo [3:44]. Mezclar ambos estilos dentro de un proyecto es válido y, en ocasiones, produce código más limpio que reescribir todo por obligación.

Lo esencial es contar con el toolkit completo de la asincronía moderna: entender las promesas por dentro, saber escribir y leer async await, manejar errores con try catch, y elegir conscientemente entre ejecución secuencial y paralela según el caso.

¿Has encontrado algún caso donde prefieras mantener .then en lugar de refactorizar a async await? Comparte tu experiencia en los comentarios.