TechLead

JavaScript Asincrono

Callbacks, Promises, async/await

Programacion Asincrona

JavaScript es single-threaded pero puede manejar operaciones asincronas sin bloquear la ejecucion. Esto es crucial para operaciones como peticiones de red, timers y manejo de archivos.

Callbacks

// Callback basico
function obtenerDatos(callback) {
  setTimeout(() => {
    const datos = { id: 1, nombre: "Ana" };
    callback(datos);
  }, 1000);
}

obtenerDatos((datos) => {
  console.log(datos); // { id: 1, nombre: "Ana" }
});

// Callback hell (problema con callbacks anidados)
obtenerUsuario(id, (usuario) => {
  obtenerPedidos(usuario.id, (pedidos) => {
    obtenerDetalles(pedidos[0].id, (detalles) => {
      // Codigo muy anidado y dificil de leer
    });
  });
});

Promises

// Creando una Promise
const miPromesa = new Promise((resolve, reject) => {
  const exito = true;

  setTimeout(() => {
    if (exito) {
      resolve({ id: 1, nombre: "Ana" });
    } else {
      reject(new Error("Algo salio mal"));
    }
  }, 1000);
});

// Consumiendo una Promise
miPromesa
  .then((datos) => {
    console.log("Exito:", datos);
    return datos.id; // Retorna valor para siguiente .then
  })
  .then((id) => {
    console.log("ID:", id);
  })
  .catch((error) => {
    console.error("Error:", error.message);
  })
  .finally(() => {
    console.log("Siempre se ejecuta");
  });

async/await

// Funcion asincrona
async function obtenerUsuario() {
  try {
    const respuesta = await fetch("/api/usuario");
    const usuario = await respuesta.json();
    return usuario;
  } catch (error) {
    console.error("Error:", error);
    throw error;
  }
}

// Llamar funcion asincrona
obtenerUsuario()
  .then(usuario => console.log(usuario))
  .catch(error => console.error(error));

// O dentro de otra funcion async
async function main() {
  const usuario = await obtenerUsuario();
  console.log(usuario);
}
main();

Fetch API

// GET request
async function obtenerDatos() {
  const respuesta = await fetch("https://api.ejemplo.com/datos");

  if (!respuesta.ok) {
    throw new Error(`HTTP error! status: ${respuesta.status}`);
  }

  const datos = await respuesta.json();
  return datos;
}

// POST request
async function crearUsuario(usuario) {
  const respuesta = await fetch("https://api.ejemplo.com/usuarios", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(usuario)
  });

  return respuesta.json();
}

// Uso
crearUsuario({ nombre: "Ana", email: "ana@ejemplo.com" })
  .then(nuevoUsuario => console.log(nuevoUsuario));

Multiples Promesas

const promesa1 = fetch("/api/usuarios");
const promesa2 = fetch("/api/productos");
const promesa3 = fetch("/api/pedidos");

// Promise.all - espera a que todas se resuelvan
const resultados = await Promise.all([promesa1, promesa2, promesa3]);
// Si una falla, todas fallan

// Promise.allSettled - espera a todas, sin importar resultado
const resultados2 = await Promise.allSettled([promesa1, promesa2, promesa3]);
// [{ status: "fulfilled", value: ... }, { status: "rejected", reason: ... }]

// Promise.race - retorna la primera en resolver/rechazar
const primeraRespuesta = await Promise.race([promesa1, promesa2]);

// Promise.any - retorna la primera en resolver (ignora rechazos)
const primeraExitosa = await Promise.any([promesa1, promesa2]);