concurrentPool
Como concurrent, pero emite los resultados por orden de finalización — el primero que acaba es el primero que sale.
Lección
concurrentPool(n) mantiene hasta n peticiones en
vuelo contra la fuente de aguas arriba, igual que concurrent(n)
— pero te devuelve los resultados en el orden en que terminan,
no en el que empezaron. Piénsalo como un pool de workers: en cuanto se libera
un hueco, se lanza en él el siguiente elemento pendiente, y el primero que
acaba es el primero que se emite. Esto coincide con el
concurrentPool de FxTS y es la herramienta adecuada cuando no te
importa qué resultado vino de qué entrada — solo quieres reaccionar a cada
resultado en cuanto está listo (por ejemplo, actualizar una lista de progreso
conforme aterriza cada fetch), en lugar de bloquearte con el más lento para
conservar el orden.
A diferencia de concurrent, que se guía por el marcador de
demanda que llega de aguas abajo, concurrentPool mantiene
su pool lleno de forma ansiosa: desde el primer pull conserva hasta
n peticiones en vuelo, haya los consumidores que haya
esperando. Incluso un operador terminal que tira de uno en uno como
.toList() o .each() obtiene todo el solapamiento
— y ve los resultados en el orden en que terminan.
Demo 1 · Orden de finalización
El elemento 1 es el más lento (300ms) y el 2 el más rápido (100ms) — el
resultado sale con el más rápido primero, directamente desde .toList():
Demo 2 · Contraste con concurrent
Los mismos retardos, el mismo pool de tamaño 3 — la única diferencia es en qué orden llegan los resultados:
Pruébalo tú
Ejercicio: este pool de tamaño 1 procesa los elementos de uno en uno, en el orden en que se lanzan. Súbelo a 3 para que los tres compitan a la vez y observa cómo el orden impreso pasa a ser el de finalización.
concurrent — variante que preserva el orden ·
toAsync — el modelo basado en pull en el que se apoya ·
puentes con Stream — aplica concurrentPool antes de toStream() ·
debounce — limitación de frecuencia para callbacks