Async/await: patrones seguros y errores comunes
Async/await: patrones seguros y errores comunes
Las promesas y async/await son la forma moderna de escribir código asíncrono en Node. La sintaxis parece síncrona y eso la hace legible, pero esconde trampas que provocan fugas de memoria, peticiones que nunca responden y errores que se pierden en silencio. Dominar tres patrones te evita el 90% de los problemas.
1. Paralelizar cuando las operaciones son independientes
Si dos consultas no dependen una de la otra, esperarlas en secuencia desperdicia tiempo. Promise.all las lanza a la vez.
// Lento: 200ms + 150ms = 350ms
const user = await getUser(id);
const orders = await getOrders(id);
// Rápido: max(200ms, 150ms) = 200ms
const [user, orders] = await Promise.all([
getUser(id),
getOrders(id),
]);Atención
Con Promise.all, si una promesa falla, todo el conjunto se rechaza. Cuando quieras el resultado de todas aunque alguna falle, usa Promise.allSettled y revisa el status de cada una.
2. Captura los errores en un solo lugar
En Express, en lugar de envolver cada handler en try/catch, usa un pequeño envoltorio que reenvía cualquier error al middleware de errores:
const asyncHandler = (fn) => (req, res, next) =>
Promise.resolve(fn(req, res, next)).catch(next);
app.get('/users/:id', asyncHandler(async (req, res) => {
const user = await getUser(req.params.id);
if (!user) return res.status(404).json({ error: 'no encontrado' });
res.json(user);
}));3. No dejes promesas colgadas
Llamar a una función async sin await ni .catch() crea una promesa flotante: si falla, genera un unhandled rejection que puede tumbar el proceso. Si de verdad no quieres esperarla, captura su error explícitamente.
Tienes tres consultas independientes que tardan 100ms cada una. ¿Cómo las resuelves en ~100ms en vez de 300ms?
Ejercicio práctico
Objetivo: optimizar y blindar código asíncrono.
- Escribe dos funciones
fakeFetch(ms, label)que resuelvan tras unsetTimeout. - Llámalas primero en secuencia con dos
awaity mide el tiempo conconsole.time. - Conviértelas a
Promise.ally compara los tiempos. - Crea el envoltorio
asyncHandlery úsalo en una ruta que lance un error a propósito; comprueba que el error llega al middleware global.
Entregable: el código con ambos tiempos comentados y la captura del error manejado sin que el proceso muera.
Para recordar
Promise.allpara operaciones independientes;allSettledcuando toleras fallos parciales.- Un
asyncHandlerreenvía errores al middleware y evita try/catch repetido. - Toda promesa necesita un
awaito un.catch(); nunca la dejes flotando.