Curso de JavaScript para Principiantes - Lección 11: Introducción a la Programación Asíncrona
¡Bienvenido a la undécima lección! Hasta ahora, has aprendido a
manipular el DOM y responder a eventos, haciendo tus páginas web
interactivas. Pero, ¿qué pasa cuando necesitas cargar datos de un
servidor, como una lista de productos o el perfil de un usuario? Estas
operaciones toman tiempo, y JavaScript usa la programación
asíncrona para manejarlas sin congelar la página. Si en PHP
haces consultas a una base de datos con mysqli
o
PDO
y esperas los resultados, en JavaScript la programación
asíncrona es como esa espera, pero en el navegador y con un enfoque más
dinámico.
¿Qué es la programación asíncrona?
En JavaScript, el código normalmente se ejecuta de forma síncrona, línea por línea. Pero algunas operaciones, como pedir datos a un servidor o esperar un temporizador, son asíncronas porque no se completan de inmediato. La programación asíncrona permite que JavaScript continúe ejecutando otro código mientras espera que esas operaciones terminen.
Ejemplo mental: Imagina que estás cocinando. Mientras esperas que el agua hierva (una tarea asíncrona), puedes picar verduras en lugar de quedarte parado. JavaScript hace lo mismo: sigue trabajando en otras tareas mientras espera una respuesta.
Conexión con PHP: En PHP, una consulta a una base de
datos (SELECT * FROM usuarios
) detiene el script hasta que
recibe los datos. En JavaScript, usas herramientas como
promesas o async/await
para evitar que la página se "congele" mientras esperas datos de una
API.
1. Entendiendo las Promesas
Una promesa es un objeto que representa una operación asíncrona que eventualmente se completará (o fallará). Una promesa puede estar en uno de tres estados:
- Pendiente: La operación aún no ha terminado.
- Cumplida: La operación se completó con éxito y devolvió un valor.
- Rechazada: La operación falló y devolvió un error.
Sintaxis básica:
let promesa = new Promise((resolve, Hawkins) => {
// Simula una operación asíncrona
setTimeout(() => {
if (Math.random() > 0.5) {
resolve("¡Éxito!");
} else {
reject("Error: Algo salió mal");
}
}, 1000); // Espera 1 segundo
});
Usando una promesa:
promesa
.then(resultado => {
console.log(resultado); // Imprime: ¡Éxito!
})
.catch(error => {
console.log(error); // Imprime: Error: Algo salió mal
});
.then()
: Ejecuta una función si la promesa se cumple..catch()
: Ejecuta una función si la promesa falla.
2. Ejemplo Práctico: Simulando una Carga de Datos
Vamos a simular una operación asíncrona, como cargar datos de un servidor.
Ejemplo:
function cargarDatos() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let exito = Math.random() > 0.3; // 70% de probabilidad de éxito
if (exito) {
resolve(["Manzana", "Banana", "Naranja"]);
} else {
reject("Error al cargar los datos");
}
}, 2000); // Espera 2 segundos
});
}
cargarDatos()
.then(datos => {
console.log("Datos cargados:", datos);
})
.catch(error => {
console.log(error);
});
Cómo funciona:
- La función
cargarDatos
devuelve una promesa. - Después de 2 segundos, la promesa se resuelve con un arreglo de frutas o se rechaza con un error.
.then()
maneja los datos exitosos, y.catch()
maneja los errores.
3. Usando async/await
La sintaxis async/await
es una forma
más limpia y legible de trabajar con promesas, haciendo que el código
asíncrono parezca síncrono.
Sintaxis:
- Declara una función como
async
. - Usa
await
dentro de la función para esperar el resultado de una promesa.
Ejemplo con async/await
:
async function obtenerDatos() {
try {
let datos = await cargarDatos();
console.log("Datos cargados:", datos);
} catch (error) {
console.log(error);
}
}
obtenerDatos();
async
: Indica que la función devuelve una promesa.await
: Pausa la ejecución hasta que la promesa se resuelva.try/catch
: Maneja errores, similar a.catch()
.
Conexión con PHP: Esto es como usar
try/catch
en PHP para manejar excepciones en una consulta a
una base de datos, pero aplicado a operaciones asíncronas en el
navegador.
4. Ejemplo Realista: Cargar Datos de una API
Vamos a usar la función fetch
para cargar datos de una
API pública, algo similar a hacer una consulta HTTP en PHP con
curl
.
HTML:
<!DOCTYPE html>
<html>
<head>
<title>API de Usuarios</title>
</head>
<body>
<h1>Usuarios</h1>
<ul id="lista-usuarios"></ul>
<button id="cargar">Cargar Usuarios</button>
<script src="script.js"></script>
</body>
</html>
JavaScript (script.js):
let boton = document.getElementById("cargar");
let lista = document.getElementById("lista-usuarios");
async function cargarUsuarios() {
try {
let respuesta = await fetch("https://jsonplaceholder.typicode.com/users");
let usuarios = await respuesta.json();
lista.innerHTML = ""; // Limpia la lista
usuarios.forEach(usuario => {
let li = document.createElement("li");
li.textContent = usuario.name;
lista.appendChild(li);
});
} catch (error) {
lista.innerHTML = "<li>Error al cargar usuarios</li>";
}
}
boton.addEventListener("click", cargarUsuarios);
Cómo funciona:
fetch
: Hace una solicitud HTTP a una API (similar acurl
en PHP).await fetch(...)
: Espera la respuesta de la API.await respuesta.json()
: Convierte la respuesta a un objeto JavaScript.- Los nombres de los usuarios se añaden a una lista en el DOM.
- Si hay un error (como fallo de red), se muestra un mensaje de error.
Conexión con PHP: Esto es como usar
file_get_contents
o curl
en PHP para obtener
datos de una API, pero en JavaScript se hace en el navegador y se
actualiza la página dinámicamente.
5. Buenas Prácticas
- Maneja errores siempre: Usa
.catch()
otry/catch
para evitar que los errores rompan tu aplicación. - Indica carga al usuario: Muestra un mensaje como "Cargando..." mientras esperas datos (puedes modificar el DOM).
- Evita promesas anidadas: Usa
async/await
para mantener el código legible. - Valida datos de la API: Verifica que los datos recibidos sean válidos antes de usarlos.
- Prueba en un entorno real: Usa JSFiddle o un archivo HTML local para
probar
fetch
con APIs públicas.
Ejercicios Prácticos
-
Temporizador simple:
- Crea una promesa que espere 3 segundos y resuelva con el mensaje "¡Tiempo cumplido!".
- Usa
.then()
para mostrar el mensaje en la consola.
-
Carga de datos simulada:
- Crea una función que devuelva una promesa que, tras 2 segundos, resuelva con un arreglo de 3 nombres o falle con un error.
- Usa
async/await
para manejar la promesa y mostrar los nombres en la consola.
-
Cargar fotos de una API:
- Crea un HTML con un
<button>
y un<div>
vacío. - Al hacer clic en el botón, usa
fetch
con la APIhttps://jsonplaceholder.typicode.com/photos
para cargar los primeros 5 títulos de fotos y mostrarlos en el<div>
como una lista (<ul>
).
- Crea un HTML con un
-
Formulario con validación asíncrona:
- Crea un HTML con un
<input>
para un nombre de usuario y un<button>
. - Al hacer clic, simula una validación asíncrona (con una promesa que espere 1 segundo) que resuelva con "Usuario válido" si el nombre tiene más de 3 caracteres, o falle con "Nombre demasiado corto".
- Muestra el resultado en un
<p>
.
- Crea un HTML con un
Instrucción: Prueba estos ejercicios en JSFiddle o en un archivo HTML local con
un <script>
. Por ejemplo:
async function ejemplo() {
let datos = await new Promise(resolve => setTimeout(() => resolve("¡Hecho!"), 1000));
console.log(datos);
}
ejemplo();
Para la Próxima Lección
En la Lección 12, trabajaremos en un proyecto final: una aplicación simple, como una lista de tareas interactiva, que combine todo lo aprendido (variables, funciones, DOM, eventos, y asincronía). ¡Sigue practicando la programación asíncrona con los ejercicios de hoy para estar listo!