Capítulo 4.5: Async/await vs Promise
Tiempo de estudio: 30 minutos
1. Asincronía: Dos formas de gestionar la "comunicación espacial"
Imagina que el Centro de Control de Misiones (MCC) envía una orden a Marte. La respuesta tardará varios minutos en llegar. ¿Cómo organizar el trabajo durante ese tiempo?
Método 1: "Protocolo de devolución de llamada" (Promise con .then()
)
Envías una orden y das una instrucción: "CUANDO llegue la respuesta, ENTONCES ejecuta esta función". Esto se asemeja a una cadena de eventos.
Método 2: "Modo de espera" (Async/await) Dices: "Esperaré la respuesta a esta orden, pero no bloquearé otros paneles de control". Es como si pausaras la ejecución de esta tarea específica, permitiendo que el resto del MCC siga funcionando.
Ambos métodos resuelven la misma tarea: gestionar operaciones asíncronas. async/await
es simplemente una sintaxis más moderna y legible que funciona "sobre" las promesas.
💡 Analogía espacial:
- Promise con
.then()
: Es como escribir en un post-it: "Cuando el rover de Marte envíe una foto, pásala al departamento de análisis".- Async/await: Es como decirle a un asistente: "Espera la foto del rover de Marte, mientras yo me ocupo de los cálculos para el lanzamiento de un nuevo cohete".
2. Promise con .then()
: Cadena de comandos clásica
Esta es la forma fundamental de trabajar con la asincronía en JavaScript, que utilizamos en el capítulo 4.1.
Recordemos nuestro primer código:
function getIssPositionWithPromises() {
console.log('Enviando solicitud mediante el protocolo "Promise"...');
fetch('http://api.open-notify.org/iss-now.json')
.then(response => {
// Etapa 1: Respuesta recibida
if (!response.ok) {
throw new Error(`Error HTTP: ${response.status}`);
}
return response.json(); // Devolvemos una nueva promesa
})
.then(data => {
// Etapa 2: Datos parseados
console.log('Datos recibidos mediante el protocolo "Promise":', data.iss_position);
})
.catch(error => {
// Etapa 3 (Error): Algo salió mal en alguna de las etapas
console.error('Fallo de comunicación mediante el protocolo "Promise":', error);
});
console.log('...comando enviado, el MCC sigue trabajando...');
}
Ventajas:
- Cadena de acciones explícita.
- Adecuado para operaciones secuenciales simples.
Desventajas:
- "Infierno de las devoluciones de llamada" (Callback Hell): Con un gran número de operaciones asíncronas anidadas, el código puede convertirse en una "escalera" de
.then()
difícil de leer. - El manejo de errores puede ser menos intuitivo.
3. Async/await: Estilo síncrono moderno
async/await
es "azúcar sintáctico" sobre las promesas, que permite escribir código asíncrono como si fuera síncrono.
Reglas de uso:
- La palabra clave
await
solo se puede usar dentro de una función marcada comoasync
. await
se coloca antes de una llamada que devuelve una promesa (por ejemplo,fetch()
oresponse.json()
).await
"pausa" la ejecución de la funciónasync
hasta que la promesa se resuelva y devuelve su resultado.
El mismo código, reescrito con async/await
:
async function getIssPositionWithAsyncAwait() {
console.log('Enviando solicitud mediante el protocolo "Async/await"...');
try {
// Etapa 1: Esperamos la respuesta del servidor
const response = await fetch('http://api.open-notify.org/iss-now.json');
if (!response.ok) {
throw new Error(`Error HTTP: ${response.status}`);
}
// Etapa 2: Esperamos a que el cuerpo de la respuesta se convierta a JSON
const data = await response.json();
console.log('Datos recibidos mediante el protocolo "Async/await":', data.iss_position);
} catch (error) {
// Etapa 3 (Error): Capturamos cualquier error del bloque try
console.error('Fallo de comunicación mediante el protocolo "Async/await":', error);
}
console.log('...comando enviado, el MCC sigue trabajando...');
}
Ventajas:
- Legibilidad: El código se ve casi como código síncrono normal, es fácil de leer de arriba abajo.
- Manejo de errores: Se utiliza el bloque
try...catch
estándar y familiar. - Depuración: Es mucho más fácil de depurar, ya que se pueden establecer puntos de interrupción (breakpoints) en cada línea con
await
.
Desventajas:
- Es fácil olvidar
await
oasync
, lo que provocará errores.
4. ¿Cuándo usar qué protocolo?
Situación | Enfoque recomendado | ¿Por qué? |
---|---|---|
La mayoría de los casos | async/await |
El código es más limpio, más fácil de leer y depurar. Es el estándar moderno. |
Cadena simple de 1-2 acciones | Promise con .then() |
Funciona bien, el código sigue siendo compacto. |
Ejecución paralela de múltiples solicitudes | Promise.all() |
Este método permite ejecutar varias promesas simultáneamente y esperar a que todas se completen. async/await se combina perfectamente con él. |
Ejemplo con Promise.all()
:
async function getParallelData() {
try {
// Iniciamos ambas solicitudes simultáneamente
const [shipsResponse, launchesResponse] = await Promise.all([
fetch('https://api.spacexdata.com/v4/rockets'),
fetch('https://api.spacexdata.com/v4/launches/latest')
]);
if (!shipsResponse.ok || !launchesResponse.ok) {
throw new Error('¡Una de las solicitudes falló!');
}
const rockets = await shipsResponse.json();
const latestLaunch = await launchesResponse.json();
console.log(`Total de cohetes en la flota: ${rockets.length}`);
console.log(`Último lanzamiento: ${latestLaunch.name}`);
} catch (error) {
console.error('Error al obtener datos paralelos:', error);
}
}
Cuestionario de refuerzo
🚀 Resumen del capítulo:
Has aprendido dos sintaxis para gestionar operaciones asíncronas y entendido por qué async/await
es la preferida en la mayoría de los proyectos modernos.
- 🔗 Has refrescado tus conocimientos sobre Promise con
.then()
. - 🛠️ Has comprendido en profundidad cómo funciona
async/await
y sus ventajas. - ⚡ Has aprendido sobre
Promise.all
para ejecutar peticiones paralelas.
¡Protocolos de comunicación aprendidos! En el capítulo final de esta sección, uniremos todos nuestros conocimientos y construiremos nuestro "Centro de Control de Vuelo", creando una interfaz completa para todas las operaciones CRUD.
📌 Práctica:
- Reescribe todas las funciones en tu
app.js
que aún utilizan.then()
al sintaxisasync/await
.- Intenta añadir otra petición en
Promise.all()
(por ejemplo, ahttps://api.spacexdata.com/v4/starlink
) y muestra los datos.⚠️ Si hay errores:
await is only valid in async functions
: Asegúrate de que la función donde utilizasawait
esté marcada comoasync
.- La variable contiene
[object Promise]
: Has olvidado ponerawait
delante de la función que devuelve una promesa. ```