Programación asíncrona en JavaScript: guía completa para principiantes

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción a la programación asíncrona en JavaScript

\n\n

JavaScript es un lenguaje de programación de un solo hilo. Esto significa que en cada momento solo se ejecuta una operación. Sin embargo, si todas las operaciones se ejecutaran secuencialmente, el navegador se "congelaría" al cargar datos del servidor o leer un archivo. Aquí es donde la programación asíncrona viene al rescate.

\n\n

La programación asíncrona permite ejecutar operaciones largas (solicitudes a API, lectura de archivos, temporizadores) sin bloquear el hilo principal de ejecución. En lugar de esperar a que finalice una tarea, el código continúa ejecutándose y el resultado se procesa más tarde. Este es un concepto clave para crear aplicaciones rápidas y receptivas en Node.js.

\n\n

En esta guía, analizaremos tres enfoques principales para la programación asíncrona: callbacks, promesas y la sintaxis async/await. Aprenderás a trabajar correctamente con código asíncrono y evitar los errores típicos de los principiantes.

\n\n

1. Callbacks: la base de la asincronía

\n\n

Un callback es una función que se pasa como argumento a otra función y se llama después de que se completa una operación asíncrona. Es la forma más antigua y básica de trabajar con asincronía en JavaScript.

\n\n

Ejemplo con setTimeout

\n\n

La función incorporada setTimeout es un ejemplo clásico de operación asíncrona. Toma un callback y un retardo en milisegundos:

\n\n
console.log('Inicio');\n\nsetTimeout(() => {\n    console.log('Pasaron 2 segundos');\n}, 2000);\n\nconsole.log('Fin');\n\n// Salida:\n// Inicio\n// Fin\n// Pasaron 2 segundos
\n\n

Observa que "Fin" se muestra antes que el mensaje del callback. Esto es la asincronía: el código no espera a que setTimeout termine.

\n\n

El problema del "Callback Hell"

\n\n

Cuando tienes muchas operaciones asíncronas anidadas, el código se vuelve difícil de leer. Este fenómeno se llama "infierno de callbacks" (Callback Hell):

\n\n
fs.readFile('archivo1.txt', (err, data1) => {\n    if (err) throw err;\n    fs.readFile('archivo2.txt', (err, data2) => {\n        if (err) throw err;\n        fs.readFile('archivo3.txt', (err, data3) => {\n            if (err) throw err;\n            console.log(data1, data2, data3);\n        });\n    });\n});
\n\n

Este código es difícil de mantener y depurar. Afortunadamente, JavaScript moderno ofrece soluciones más elegantes.

\n\n

2. Promesas: manejo elegante de la asincronía

\n\n

Una Promise (promesa) es un objeto que representa el resultado de una operación asíncrona. Una promesa puede estar en uno de tres estados:

\n\n
    \n
  • Pending (pendiente) — estado inicial, la operación aún no ha terminado
  • \n
  • Fulfilled (cumplida) — la operación se completó con éxito
  • \n
  • Rejected (rechazada) — la operación se completó con un error
  • \n
\n\n

Creación y uso de una Promise

\n\n
const miPromesa = new Promise((resolve, reject) => {\n    setTimeout(() => {\n        const exito = true;\n        if (exito) {\n            resolve('Datos obtenidos');\n        } else {\n            reject('Error al obtener datos');\n        }\n    }, 2000);\n});\n\nmiPromesa\n    .then(resultado => {\n        console.log(resultado); // "Datos obtenidos"\n    })\n    .catch(error => {\n        console.error(error); // "Error al obtener datos"\n    })\n    .finally(() => {\n        console.log('Operación completada');\n    });
\n\n

Encadenamiento de promesas (Chaining)

\n\n

Las promesas se pueden encadenar, lo que permite evitar el "infierno de callbacks":

\n\n
function leerArchivo(nombreArchivo) {\n    return new Promise((resolve, reject) => {\n        fs.readFile(nombreArchivo, 'utf8', (err, data) => {\n            if (err) reject(err);\n            else resolve(data);\n        });\n    });\n}\n\nleerArchivo('archivo1.txt')\n    .then(data1 => {\                

Blogs

Book Recommendations