Programación Asíncrona
Programación Asíncrona Fundamental
Section titled “Programación Asíncrona ”Callbacks Básico
Section titled “Callbacks ”Callbacks básicos
Section titled “Callbacks básicos”// Función con callbackfunction obtenerDatos(callback) { setTimeout(() => { const datos = { id: 1, nombre: 'Juan' }; callback(datos); }, 1000);}
// UsoobtenerDatos((datos) => { console.log(datos);});Callback Hell
Section titled “Callback Hell”obtenerUsuario(1, (usuario) => { obtenerPosts(usuario.id, (posts) => { obtenerComentarios(posts[0].id, (comentarios) => { obtenerAutor(comentarios[0].autorId, (autor) => { console.log(autor); }); }); });});Promesas Importante
Section titled “Promesas ”Crear promesas
Section titled “Crear promesas”// Crear una promesaconst miPromesa = new Promise((resolve, reject) => { setTimeout(() => { const exito = true; if (exito) { resolve('Operación exitosa'); } else { reject('Algo salió mal'); } }, 1000);});
// Usar la promesamiPromesa .then(resultado => console.log(resultado)) .catch(error => console.error(error));Encadenar promesas
Section titled “Encadenar promesas”obtenerUsuario(1) .then(usuario => obtenerPosts(usuario.id)) .then(posts => obtenerComentarios(posts[0].id)) .then(comentarios => obtenerAutor(comentarios[0].autorId)) .then(autor => console.log(autor)) .catch(error => console.error(error));Promise.all y Promise.race
Section titled “Promise.all y Promise.race”// Ejecutar promesas en paraleloconst promesa1 = fetch('/api/usuarios');const promesa2 = fetch('/api/posts');
// Esperar que todas se completenPromise.all([promesa1, promesa2]) .then(([usuarios, posts]) => { console.log(usuarios, posts); }) .catch(error => console.error(error));
// Obtener la primera que se completePromise.race([promesa1, promesa2]) .then(resultado => console.log(resultado)) .catch(error => console.error(error));async/await Moderno
Section titled “async/await ”Sintaxis básica
Section titled “Sintaxis básica”async function obtenerRespuesta() { try { // Hacer la petición a la API const respuesta = await fetch('https://yesno.wtf/api'); const datos = await respuesta.json();
// Extraer la respuesta y la imagen return { respuesta: datos.answer, // 'yes' o 'no' imagen: datos.image // URL del GIF }; } catch (error) { console.error('Error:', error); throw error; }}
// Usoconst resultado = await obtenerRespuesta();console.log(resultado);// { respuesta: 'yes', imagen: 'https://yesno.wtf/assets/yes/2.gif' }async function obtenerDatos() { try { const usuario = await obtenerUsuario(1); const posts = await obtenerPosts(usuario.id); const comentarios = await obtenerComentarios(posts[0].id); return comentarios; } catch (error) { console.error('Error:', error); throw error; }}Paralelismo con async/await
Section titled “Paralelismo con async/await”async function obtenerDatosParalelo() { try { // Iniciar todas las promesas const usuarioPromise = obtenerUsuario(1); const postsPromise = obtenerPosts(1);
// Esperar que todas se completen const [usuario, posts] = await Promise.all([ usuarioPromise, postsPromise ]);
return { usuario, posts }; } catch (error) { console.error('Error:', error); throw error; }}Patrones avanzados Avanzado
Section titled “Patrones avanzados ”Retry pattern
Section titled “Retry pattern”async function conReintentos(fn, maxIntentos = 3) { for (let intento = 1; intento <= maxIntentos; intento++) { try { return await fn(); } catch (error) { if (intento === maxIntentos) throw error; console.warn(`Intento ${intento} fallido, reintentando...`); await new Promise(r => setTimeout(r, 1000 * intento)); } }}Timeout pattern
Section titled “Timeout pattern”function conTimeout(promesa, ms) { const timeout = new Promise((_, reject) => { setTimeout(() => reject(new Error('Timeout')), ms); });
return Promise.race([promesa, timeout]);}
// Usoasync function obtenerDatos() { try { const resultado = await conTimeout( fetch('https://api.ejemplo.com/datos'), 5000 ); return resultado.json(); } catch (error) { console.error('Error o timeout:', error); throw error; }}Mejores prácticas Recomendado
Section titled “Mejores prácticas ”Manejo de errores
Section titled “Manejo de errores”// ❌ Maloasync function obtenerDatos() { const datos = await fetch('/api/datos'); return datos.json();}
// ✅ Buenoasync function obtenerDatos() { try { const respuesta = await fetch('/api/datos'); if (!respuesta.ok) { throw new Error(`HTTP error! status: ${respuesta.status}`); } const datos = await respuesta.json(); return datos; } catch (error) { console.error('Error al obtener datos:', error); throw error; }}Limpieza de recursos
Section titled “Limpieza de recursos”class RecursoAsíncrono { constructor() { this.controlador = new AbortController(); }
async obtenerDatos() { try { const respuesta = await fetch('/api/datos', { signal: this.controlador.signal }); return await respuesta.json(); } catch (error) { if (error.name === 'AbortError') { console.log('Solicitud cancelada'); } throw error; } }
cancelar() { this.controlador.abort(); }}Caché de promesas
Section titled “Caché de promesas”class CachePromesas { constructor() { this.cache = new Map(); }
async obtener(key, promesaFn) { if (!this.cache.has(key)) { this.cache.set(key, promesaFn()); } return this.cache.get(key); }
limpiar(key) { if (key) { this.cache.delete(key); } else { this.cache.clear(); } }}
// Usoconst cache = new CachePromesas();const datos = await cache.obtener('usuario-1', () => fetch('/api/usuarios/1').then(r => r.json()));
🐝