L55 - Callbacks
🧠 Concepto
Section titled “🧠 Concepto”Un callback es una función que se pasa como argumento a otra función para que sea ejecutada más tarde, ya sea de forma síncrona (inmediata) o asíncrona (cuando ocurra un evento o se complete una operación).
JavaScript trata las funciones como ciudadanos de primera clase: pueden asignarse a variables, pasarse como argumentos y retornarse desde otras funciones.
💻 Callbacks síncronos
Section titled “💻 Callbacks síncronos”Los callbacks síncronos se ejecutan inmediatamente dentro de la función que los recibe:
function procesarArray(arr, callback) { for (let i = 0; i < arr.length; i++) { arr[i] = callback(arr[i]); } return arr;}
const numeros = [1, 2, 3];const duplicados = procesarArray(numeros, n => n * 2);console.log(duplicados); // [2, 4, 6]Ejemplos nativos de callbacks síncronos
Section titled “Ejemplos nativos de callbacks síncronos”// forEach[1, 2, 3].forEach(n => console.log(n));
// mapconst cuadrados = [1, 2, 3].map(n => n ** 2);
// filterconst pares = [1, 2, 3, 4].filter(n => n % 2 === 0);
// sort[3, 1, 2].sort((a, b) => a - b);
// reduceconst suma = [1, 2, 3].reduce((acc, n) => acc + n, 0);💻 Callbacks asíncronos
Section titled “💻 Callbacks asíncronos”Se ejecutan más tarde, cuando una operación asíncrona termina:
// setTimeoutsetTimeout(() => { console.log('Esto se ejecuta después de 1 segundo');}, 1000);
// Event listenersbtn.addEventListener('click', () => { console.log('El usuario hizo clic');});
// readFile (Node.js)fs.readFile('datos.txt', 'utf8', (err, data) => { if (err) console.error(err); else console.log(data);});⚠️ Callback Hell (La pirámide de la perdición)
Section titled “⚠️ Callback Hell (La pirámide de la perdición)”Cuando se anidan muchos callbacks, el código se vuelve ilegible:
obtenerUsuario(id, (err, usuario) => { if (err) { console.error(err); } else { obtenerPedidos(usuario.id, (err, pedidos) => { if (err) { console.error(err); } else { obtenerDetalles(pedidos[0].id, (err, detalle) => { if (err) { console.error(err); } else { console.log('Detalle:', detalle); } }); } }); }});Problemas del callback hell
Section titled “Problemas del callback hell”- Legibilidad: el código crece hacia la derecha y es difícil de seguir.
- Manejo de errores repetitivo: hay que verificar
erren cada nivel. - Dificultad para mantener: añadir un paso extra implica reestructurar todo.
- Dificultad para depurar: el stack trace se pierde entre callbacks.
🎯 Cómo evitar el callback hell
Section titled “🎯 Cómo evitar el callback hell”1. Promesas
Section titled “1. Promesas”Encadenar .then() en lugar de anidar:
obtenerUsuario(id) .then(usuario => obtenerPedidos(usuario.id)) .then(pedidos => obtenerDetalles(pedidos[0].id)) .then(detalle => console.log(detalle)) .catch(err => console.error(err));2. Async/await
Section titled “2. Async/await”La forma más legible:
try { const usuario = await obtenerUsuario(id); const pedidos = await obtenerPedidos(usuario.id); const detalle = await obtenerDetalles(pedidos[0].id); console.log(detalle);} catch (err) { console.error(err);}3. Modularizar
Section titled “3. Modularizar”Extraer funciones nombradas en lugar de usar anónimas:
function onUsuario(err, usuario) { if (err) return console.error(err); obtenerPedidos(usuario.id, onPedidos);}
function onPedidos(err, pedidos) { if (err) return console.error(err); obtenerDetalles(pedidos[0].id, onDetalle);}
function onDetalle(err, detalle) { if (err) return console.error(err); console.log(detalle);}
obtenerUsuario(id, onUsuario);📝 Patrones útiles con callbacks
Section titled “📝 Patrones útiles con callbacks”Callback con manejo de errores (Node style)
Section titled “Callback con manejo de errores (Node style)”function dividir(a, b, callback) { if (b === 0) { callback(new Error('No se puede dividir por cero')); } else { callback(null, a / b); }}
dividir(10, 2, (err, resultado) => { if (err) return console.error(err); console.log(resultado); // 5});Callback opcional
Section titled “Callback opcional”function fetchData(url, callback) { // ... operación ... if (typeof callback === 'function') { callback(null, datos); }}🎯 Regla de oro: usa callbacks para APIs que los requieran (eventos, middleware), pero prefiere Promesas o async/await para tu propio código asíncrono.