JavaScript de Cero a Experto / Asincronía I
Callbacks asíncronos y su infierno
Ya sabes programar UNA tarea para después. El problema real llega al encadenarlas: "cuando cargue el titular, pide sus gastos; cuando lleguen, calcula el total; si algo falla, avisa". La solución histórica — callbacks anidados — funciona… y degenera tan rápido que la comunidad le puso nombre propio: callback hell. Hoy lo construyes con tus manos para entender exactamente qué vinieron a arreglar las promesas.
El encargo con instrucciones para después
Un callback asíncrono es una función que le entregas a la tarea lenta con
la instrucción "cuando termines, ejecútala con el resultado". Simulemos un
servidor de "Mi Bolsillo" con setTimeout haciendo de demora de red:
Funciona, y el event loop de la lección pasada explica el orden: los
cargar... mandan su trabajo a la cocina y sueltan el turno — por eso el
último console.log gana. La continuación vive DENTRO del callback porque
es el único lugar donde el dato ya existe.
Bajando al infierno
Ahora agrégale la vida real: un paso más, y manejo de errores en CADA nivel (¿y si el servidor falla?). El patrón acordado era pasarle a cada función también un callback de error:
cargarTitular((titular) => {
cargarGastos(titular, (gastos) => {
calcularReporte(gastos, (reporte) => {
guardarReporte(reporte, () => {
console.log("listo... a CUATRO niveles de profundidad");
}, (error) => {
console.log("falló guardar:", error);
});
}, (error) => {
console.log("falló calcular:", error);
});
}, (error) => {
console.log("falló cargar gastos:", error);
});
}, (error) => {
console.log("falló cargar titular:", error);
});Míralo bien, porque esto era el pan de cada día del JavaScript de hace años. Los tres dolores tienen nombre:
- La pirámide: cada paso anida un nivel más; el código crece en diagonal y la lógica de negocio queda enterrada entre llaves.
- Errores repartidos: un callback de error POR NIVEL, y el manejo queda lejos — leerlo es saltar entre el final de la pirámide y su principio.
- El flujo se invierte: lo que en tu cabeza es "A, luego B, luego C" en el código es C dentro de B dentro de A. Insertar un paso en la mitad es cirugía mayor.
Nota honesta: los callbacks NO son el villano — addEventListener, map,
setTimeout los usan y son perfectos, porque ahí cada callback es UNA
reacción suelta. El infierno aparece específicamente al encadenar
SECUENCIAS asíncronas con anidación. Para eso JavaScript incorporó una
estructura nueva — la promesa — que aplana la pirámide en una cadena
recta. La construyes desde cero en la próxima lección.
En el primer playground, ¿por qué el console.log del total va DENTRO del callback de cargarGastos, en vez de después de la llamada, así: cargarGastos(titular, ...); console.log('Total:', total)?
Mini-reto
Extiende el playground del servidor simulado: 1) escribe
calcularReporte(gastos, alTerminar) que tras 800ms entregue el string
"Reporte: N gastos por $ TOTAL" (con tu Intl del módulo 6); 2)
encadénala como tercer nivel de la pirámide y siente en carne propia el
anidado; 3) cuenta cuántos niveles de indentación alcanzó tu código.
Guarda este playground: en dos lecciones lo vas a APLANAR con promesas y
la comparación te va a encantar.
Qué sigue
Ya sufriste el problema; ahora la solución. La promesa: un objeto que representa "un valor que llegará", con estados, reacciones encadenables y un solo lugar para los errores. Primero aprenderás a CONSUMIR promesas ajenas (lo que harás el 90% del tiempo) y luego a fabricarlas.