Asincronía
En JavaScript, la asincronía permite ejecutar tareas que tardan un tiempo en completarse, como leer archivos, hacer peticiones a servidores o acceder a bases de datos, sin bloquear la ejecución del resto del código. Esto es especialmente importante en Node.js, donde la eficiencia depende de no detener el event loop mientras se realizan operaciones de entrada/salida.
Callbacks
Un callback es una función que se pasa como argumento a otra función y que se ejecuta una vez que la tarea asíncrona ha finalizado. Esta fue la forma tradicional de manejar la asincronía en JavaScript.
Ejemplo con callback:
function saludar(nombre, callback) {
setTimeout(() => {
console.log(`Hola, ${nombre}`);
callback();
}, 1000);
}
saludar("Ana", () => {
console.log("Saludo finalizado");
});
En este ejemplo, la función saludar espera un segundo y luego llama al callback, permitiendo que el resto del código siga ejecutándose mientras tanto.
Promesas
Las promesas (Promise) son un enfoque más moderno para manejar operaciones asíncronas. Una promesa representa un valor que puede estar disponible ahora, en el futuro o nunca. Se pueden encadenar con .then() y manejar errores con .catch().
Ejemplo con promesa:
function obtenerDatos() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const exito = true;
if (exito) {
resolve("Datos recibidos");
} else {
reject("Error al obtener datos");
}
}, 1000);
});
}
obtenerDatos()
.then(resultado => console.log(resultado))
.catch(error => console.error(error));
Este patrón mejora la legibilidad del código y evita el llamado “callback hell” cuando se encadenan múltiples tareas asíncronas.
Async/Await
async y await son sintaxis introducidas en ES2017 que permiten escribir código asíncrono de forma más parecida al código síncrono, haciendo que las promesas sean más fáciles de leer y manejar.
Ejemplo con async/await:
function obtenerDatos() {
return new Promise(resolve => {
setTimeout(() => {
resolve("Datos recibidos");
}, 1000);
});
}
async function procesarDatos() {
console.log("Inicio");
const resultado = await obtenerDatos();
console.log(resultado);
console.log("Fin");
}
procesarDatos();
En este ejemplo, await pausa la ejecución de procesarDatos hasta que la promesa se resuelve, pero sin bloquear el event loop de Node.js.
Buenas prácticas con asincronía
Al trabajar con código asíncrono, es recomendable:
- Usar promesas o async/await en lugar de callbacks cuando sea posible, para mejorar la legibilidad.
- Manejar siempre los errores con
.catch()otry...catchalrededor deawait. - Evitar mezclar estilos (callbacks y promesas) dentro de la misma función.
- Mantener las funciones asíncronas pequeñas y especializadas, evitando hacer demasiadas tareas dentro de un mismo bloque.