Usar Promise.all / allSettled / race / any
Domina los combinadores de promesas para coordinar múltiples tareas asíncronas con criterio de producto: rapidez, tolerancia a errores o primer resultado útil.
Concurrencia en JavaScript no significa paralelismo real de CPU, sino coordinar varias operaciones asíncronas sin bloquear la UI.
Los combinadores (`all`, `allSettled`, `race`, `any`) son herramientas de orquestación: eliges uno según el contrato de negocio.
Si necesitas todo correcto, usa `all`; si quieres analizar resultados parciales, `allSettled`; si buscas el primer resultado, `race` o `any`.
El objetivo avanzado es tomar decisiones predecibles ante latencia, fallos parciales y estados de carga en frontend.
- Antes del código, decide el comportamiento esperado cuando una tarea falla o tarda demasiado.
- En apps reales lanzas varias peticiones: perfil, permisos, notificaciones, métricas. No todas tienen el mismo peso para pintar la pantalla.
- La diferencia entre una UI robusta y una frágil suele estar en cómo combinas esas promesas y qué estado devuelves en cada escenario.
- `all` es ideal para pantallas que dependen de varios datos críticos y no tienen sentido incompletas.
- `Promise.all` conserva el orden de entrada en su resultado, incluso si las promesas terminan en otro orden.
Modelo mental: coordinar promesas con intención
Antes del código, decide el comportamiento esperado cuando una tarea falla o tarda demasiado.
En apps reales lanzas varias peticiones: perfil, permisos, notificaciones, métricas. No todas tienen el mismo peso para pintar la pantalla.
La diferencia entre una UI robusta y una frágil suele estar en cómo combinas esas promesas y qué estado devuelves en cada escenario.
Promise.all: cuando todo debe estar listo
`all` es ideal para pantallas que dependen de varios datos críticos y no tienen sentido incompletas.
`Promise.all` conserva el orden de entrada en su resultado, incluso si las promesas terminan en otro orden.
Si una falla, se rechaza el bloque completo. Eso simplifica lógica cuando prefieres abortar y mostrar error global.
- Ventaja: flujo simple y rápido cuando todo es obligatorio.
- Riesgo: un fallo puntual tumba el conjunto completo.
- Buena práctica: envolver en `try/catch` y mapear a un error de UI claro.
Promise.allSettled: resiliencia con resultados parciales
Cuando una sección puede fallar sin bloquear las demás, `allSettled` suele ser mejor decisión de producto.
Recibes un array de objetos `{ status, value | reason }` para cada promesa. Así decides qué módulos renderizar y cuáles degradar.
Es especialmente útil en paneles administrativos: métricas secundarias pueden fallar sin impedir la carga principal.
Promise.race y Promise.any: ganar por velocidad
Ambos eligen el primero, pero sus reglas de error son distintas y eso cambia el comportamiento del sistema.
`race` termina con la primera promesa completada, sea éxito o error. Es útil para componer timeout con una tarea principal.
`any` devuelve el primer éxito y solo falla con `AggregateError` si todas fallan. Es ideal para mirrors o múltiples proveedores.
- Usa `race` para límites de tiempo y cancelaciones lógicas.
- Usa `any` para alta disponibilidad con varias fuentes equivalentes.
- Si usas `any`, maneja explícitamente `AggregateError` para mostrar causa consolidada.
Matriz de decisión y anti-patrones
Elegir bien evita bugs de estados imposibles y mensajes de error inconsistentes.
Pregunta clave: ¿qué necesita el usuario para seguir avanzando? Si una parte es opcional, no la trates como bloqueante total.
Documenta el contrato de cada combinador en el servicio para que el equipo no rompa ese comportamiento al refactorizar.
- `all`: datos obligatorios para habilitar la vista.
- `allSettled`: tolerancia a fallos parciales y telemetría por módulo.
- `race`: primer resultado (incluye error), útil para timeout técnico.
- `any`: primer éxito, útil para redundancia de proveedores.