async/await en Node
async/await hace que el código asíncrono de Node se lea como código síncrono, manteniendo la semántica de las Promises. La ventaja es la claridad si preservas el contexto de los errores y evitas serializar E/S independientes.
Busca en todas las páginas de la documentación
async/await hace que el código asíncrono de Node se lea como código síncrono, manteniendo la semántica de las Promises. La ventaja es la claridad si preservas el contexto de los errores y evitas serializar E/S independientes.
async function fetchUser(id: string) {
const res = await fetch(`https://api.example.com/users/${id}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json() as Promise<{ id: string; name: string }>;
}
try {
const user = await fetchUser('42');
console.log(user.name);
} catch (err) {
console.error('fetchUser failed:', err);
}Cuándo usarlo:
.then() anidadas en código existenteimport { createServer } from 'node:http';
interface User { id: string; name: string }
const users = new Map<string, User>([['1', { id: '1', name: 'Ada' }]]);
async function getUser(id: string): Promise<User> {
await new Promise((r) => setTimeout(r, 10)); // simula latencia de la base de datos
const user = users.get(id);
if (!user) throw new Error(`User ${id} not found`);
return user;
}
const server = createServer(async (req, res) => {
try {
const id = req.url?.split('/').pop() ?? '';
const user = await getUser(id);
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify(user));
} catch (err) {
const message = err instanceof Error ? err.message : 'Unknown error';
const status = message.includes('not found') ? 404 : 500;
res.writeHead(status, { 'content-type': 'application/json' });
res.end(JSON.stringify({ error: message }));
}
});
server.listen(3000);Lo que esto demuestra:
async devuelven Promises; los errores deben ser capturados por solicitudtry/catch alrededor de await mapea los fallos a códigos de estado HTTPError preserva los mensajes para clientes y registrosawait no bloquea otras solicitudes a menos que esperes serialmente dentro de un bloqueoasync function siempre devuelve una Promise, incluso si return 42.await pausa la función hasta que la Promise se resuelve, programando el resto como microtareas.async se convierten en Promises rechazadas.// Lento: secuencial (la latencia se acumula)
const a = await fetchA();
const b = await fetchB();
// Rápido: E/S independiente paralela
const [a, b] = await Promise.all([fetchA(), fetchB()]);// Patrón de resultado tipado para fallos esperados (opcional)
type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
async function safeFetch(url: string): Promise<Result<unknown>> {
try {
const res = await fetch(url);
return { ok: true, value: await res.json() };
} catch (error) {
return { ok: false, error: error instanceof Error ? error : new Error(String(error)) };
}
}try/catch o hooks de error del framework (Express 5 mejora esto).await secuencial en bucles - for (const id of ids) await fetch(id) es lento. Solución: Promise.all con límite de concurrencia (p-limit).void doWork().catch(log) intencionalmente, o await.util.promisify o fs/promises.import() dinámico perezoso para dependencias pesadas.| Alternativa | Usar cuándo | No usar cuándo |
|---|---|---|
Promises puras .then() | Interoperar con librerías de estilo callback | La legibilidad de las ramificaciones complejas se ve afectada |
Promise.allSettled | Lotes de éxito parcial | Todos deben tener éxito atómicamente |
| Streams reactivos (RxJS) | Composición de eventos a lo largo del tiempo | Manejadores simples de solicitud/respuesta |
| Código síncrono | CPU pura en datos pequeños | Cualquier E/S o red |
await suspende solo la función asíncrona, no el hilo. Otras solicitudes se ejecutan hasta que tu continuación se reanuda como una microtarea.
Envuelve en try/catch y llama a next(err), o usa un wrapper que reenvíe los rechazos al middleware de errores.
Sí, en ESM ("type": "module"). Los importadores esperan a que el módulo termine de inicializarse.
Llamar a una función asíncrona sin await o .catch() - los rechazos pueden quedar sin manejar.
Usa una librería de pool o agrupa los IDs en bloques en lugar de un Promise.all ilimitado en miles de elementos.
Sí, todos los métodos de fs/promises devuelven Promises adecuadas para await.
for await (const chunk of stream) consume iterables asíncronos, común con streams y cuerpos de fetch.
Sí, cuando realiza E/S. Asegúrate de que el framework espera los valores de retorno del middleware (Express 5, Fastify 5 lo hacen).
throw new Error('DB failed', { cause: originalErr });Preserva el contexto de pila anidado en Node 24.
Generalmente sí con await. Las mezclas profundas de callbacks sin promisificar aún pueden perder contexto.
Los valores de retorno y los errores lanzados se integran con el ciclo de vida de respuesta de Fastify; aún así, prefiere la validación explícita en los límites.
Rutas críticas con cientos de microtareas donde una máquina de estados es más clara; raro en APIs CRUD típicas.
Versiones de pila: Esta página fue escrita para Node.js 24.18.0 (LTS Activo), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.
Revisado por Chris St. John·Última actualización: 19 jul 2026