async/await
async/await es la forma más moderna y elegante de trabajar con código asíncrono en JavaScript. Es azúcar sintáctico sobre las Promises que hace que el código asíncrono parezca y se escriba como código síncrono.
Si las Promises resolvieron el problema del "Callback Hell", async/await hace que trabajar con asincronía sea tan natural como escribir código normal.
¿Qué son async/await?
async
- declara que una función es asíncronaawait
- pausa la ejecución hasta que una Promise se resuelva
Comparación Visual
Vamos a ver un ejemplo de código con Promises
y cómo se vería con async/await
para que veas la diferencia:
// ❌ Con Promises (funcional pero verboso)
function obtenerDatos() {
return fetch('/api/datos')
.then(response => response.json())
.then(datos => {
console.log(datos)
return datos
})
.catch(error => {
console.log('Error:', error)
})
}
// ✅ Con async/await (mucho más limpio)
async function obtenerDatos() {
try {
const response = await fetch('/api/datos')
const datos = await response.json()
console.log(datos)
return datos
} catch (error) {
console.log('Error:', error)
}
}
La estrategia para convertir una función con Promises a async/await es muy sencilla:
async
declara la función como asíncronaawait
pausa la ejecución hasta que la Promise se resuelvatry/catch
maneja los errores
Características Importantes
- Una función
async
siempre devuelve una Promise - Solo puedes usar
await
dentro de funcionesasync
await
pausa la ejecución hasta que la Promise se resuelva
Operaciones en Paralelo
❌ Secuencial (más lento)
async function secuencial() {
console.time('Secuencial')
const resultado1 = await esperar(1000) // Espera 1 segundo
const resultado2 = await esperar(1000) // Espera otro segundo
const resultado3 = await esperar(1000) // Espera otro segundo
console.timeEnd('Secuencial') // ~3 segundos total
return [resultado1, resultado2, resultado3]
}
✅ Paralelo (más rápido)
async function paralelo() {
console.time('Paralelo')
// Iniciamos todas las operaciones al mismo tiempo
const promesa1 = esperar(1000)
const promesa2 = esperar(1000)
const promesa3 = esperar(1000)
// Esperamos a que todas terminen
const resultados = await Promise.all([promesa1, promesa2, promesa3])
console.timeEnd('Paralelo') // ~1 segundo total
return resultados
}
paralelo().then(resultados => console.log('Resultados paralelos:', resultados))
Promise.all con async/await
async function descargarArchivos() {
function descargar(archivo, tiempo) {
return new Promise(resolve => {
setTimeout(() => {
console.log(`📁 ${archivo} descargado`)
resolve(`Contenido de ${archivo}`)
}, tiempo)
})
}
try {
console.log('🚀 Iniciando descargas paralelas...')
const archivos = await Promise.all([
descargar('imagen1.jpg', 1000),
descargar('imagen2.jpg', 1500),
descargar('video.mp4', 2000)
])
console.log('✅ Todas las descargas completadas')
return archivos
} catch (error) {
console.log('❌ Error en alguna descarga:', error)
throw error
}
}
descargarArchivos()
.then(archivos => console.log('Archivos obtenidos:', archivos.length))
.catch(error => console.log('Error final:', error))
Errores Comunes y Cómo Evitarlos
❌ Error 1: Olvidar await
// ❌ MALO: Sin await, no espera el resultado
async function malo() {
const resultado = esperar(1000) // Devuelve una Promise, no el valor
console.log(resultado) // Imprime [object Promise]
return resultado
}
// ✅ BUENO: Con await
async function bueno() {
const resultado = await esperar(1000) // Espera y obtiene el valor
console.log(resultado) // Imprime el valor real
return resultado
}
❌ Error 2: No usar async en la función
// ❌ MALO: await solo funciona en funciones async
function malo() {
const resultado = await esperar(1000) // SyntaxError!
return resultado
}
// ✅ BUENO: Función marcada como async
async function bueno() {
const resultado = await esperar(1000)
return resultado
}
❌ Error 3: Hacer operaciones secuenciales innecesariamente
// ❌ MALO: Secuencial cuando podrían ser paralelas
async function malo() {
const a = await operacion1() // Espera 1 segundo
const b = await operacion2() // Espera otro segundo
return [a, b] // Total: 2 segundos
}
// ✅ BUENO: En paralelo
async function bueno() {
const [a, b] = await Promise.all([
operacion1(), // Ambas empiezan al mismo tiempo
operacion2()
])
return [a, b] // Total: 1 segundo
}
Compatibilidad y Alternativas
Top-Level await (ES2022)
En módulos modernos, puedes usar await en el nivel superior:
// En un módulo ES6
const datos = await fetch('/api/datos')
const json = await datos.json()
console.log(json)
IIFE para navegadores antiguos
// Para usar await fuera de una función async
(async () => {
try {
const resultado = await miOperacionAsincrona()
console.log(resultado)
} catch (error) {
console.log('Error:', error)
}
})()
Resumen
¿Qué es async/await?
- Sintaxis moderna para trabajar con código asíncrono
- Azúcar sintáctico sobre las Promises
- Hace que el código asíncrono parezca síncrono
Reglas Importantes
async
declara una función asíncrona (siempre devuelve Promise)await
pausa la ejecución hasta que la Promise se resuelva- Solo puedes usar
await
dentro de funcionesasync
Ventajas sobre Promises
- ✅ Código más legible y natural
- ✅ try/catch funciona perfectamente
- ✅ Debugging más fácil
- ✅ Menos anidamiento
Mejores Prácticas
- ✅ Usa Promise.all() para operaciones paralelas
- ✅ Maneja errores con try/catch
- ✅ Considera timeouts para operaciones críticas
- ✅ Usa reintentos para operaciones inestables
Evolución Completa
Callbacks → Promises → async/await
↓ ↓ ↓
Callback Mejor Excelente
Hell legible legibilidad
¡Con async/await has completado tu viaje por la programación asíncrona en JavaScript! Ahora tienes todas las herramientas para manejar operaciones asíncronas de manera elegante y profesional.
¿Qué es async/await?
¿Qué devuelve siempre una función async?
¿Dónde puedes usar la palabra clave await?
¿Cómo se manejan los errores en async/await?
¿Cuál es la diferencia entre estas dos funciones?// Función A
async function funcionA() {
const a = await operacion1()
const b = await operacion2()
return [a, b]
}
// Función B
async function funcionB() {
const [a, b] = await Promise.all([operacion1(), operacion2()])
return [a, b]
}
// Función A
async function funcionA() {
const a = await operacion1()
const b = await operacion2()
return [a, b]
}
// Función B
async function funcionB() {
const [a, b] = await Promise.all([operacion1(), operacion2()])
return [a, b]
}
¿Qué pasará con este código?async function ejemplo() {
console.log('1')
await new Promise(resolve => setTimeout(resolve, 1000))
console.log('2')
}
console.log('A')
ejemplo()
console.log('B')
async function ejemplo() {
console.log('1')
await new Promise(resolve => setTimeout(resolve, 1000))
console.log('2')
}
console.log('A')
ejemplo()
console.log('B')
🔒 Inicio sesión requerido
Para guardar tu progreso, necesitas iniciar sesión con uno de estos servicios: