Recetas de RxJS: ‘forkJoin’ con el progreso de finalización para solicitudes de red masivas en Angular

Como me sucede a menudo — este post es solo una prolongación de mi actividad de StackOverflow:-).

Pregunta:

¿Hay alguna forma de reunir una lista de observables para obtener un resultado acumulativo como lo hace forkJoin, pero obtener algún tipo de progreso mientras terminan?

Una buena tarea para crear una función RxJS personalizada. ¡Pongámoslo en práctica!

Echemos un vistazo a la documentación oficial:

forkJoin (sources sources: any): Observable<any>

Acepta un Array de ObservableInput o un diccionario Object de ObservableInput y devuelve un Observable que emite una matriz de valores en el mismo orden exacto array, o un diccionario de valores con la misma forma que el diccionario pasado.

En otras palabras, forkJoin para Observables funciona de la misma manera que Promise.todo funciona para Promesas.

Aquí hay un diagrama de mármol:

El caso de uso posible es ejecutar muchas solicitudes de redes paralelas, por ejemplo, obtener algunos detalles de la lista de usuarios (si la API solo admite la obtención por usuario).

Aquí hay un ejemplo:

enlace de fragmento

Aquí hay un enlace de código para jugar.
Funciona bien, pero ¿qué pasa si necesitamos conocer alguna información intermedia, como cuántas solicitudes ya se han resuelto? Con la implementación actual de forkJoin, es imposible, pero podemos crear nuestra propia versión de la misma..
OK, tan breve agenda cómo debería funcionar este forkJoinWithPercent:
Salida:
1. Devuelve Observable () de orden superior (HO) que emite una matriz de dos Observables: .

<>Copiar
*Higher-order (HO) Observable - observable that emits other observables, so data flow should be handled with special flattening operators like mergeMap, switchMap, concatMap, etc... you can read more about it here and here.

2. porcentaje$ – emite porcentaje de finalización (número);
3. finalResult$ – emite una matriz final de valores al final (o error si algún argumento observable emite un valor de error).
El uso preliminar se ve así:

enlace de fragmento

Detalles de implementación:

  1. Nuestra función forkJointWithProgress acepta una matriz de Observables y debe devolver Observables de orden superior.
  2. Este Observable devuelto debe emitir un valor (usaremos of () para eso)
  3. Los efectos secundarios se agregarán a cada elemento en una matriz de observables de argumentos para calcular el porcentaje de finalización y emitir este valor con un porcentaje especial percent (usaremos el operador finalizar para calcular el porcentaje y usaremos el Sujeto como porcentaje$).
  4. finalResult provides proporciona resultados estándar de RxJS para Kjoin.
  5. El resultado observable debería funcionar de forma independiente para cada suscriptor (funcionalidad de ajuste con la función diferir de RxJS para proporcionar una ejecución limpia para cada suscriptor; puede leer más sobre este caso aquí).
  6. Si alguno de los argumentos Observables emite un error, se propagará a los suscriptores de finalResult subscribers.

Packtpub.com y preparé un curso completo de RxJS con muchos otros detalles de cómo puede resolver las tareas diarias de su desarrollador con esta increíble biblioteca. Puede ser interesante para principiantes, pero también contiene temas avanzados. Echa un vistazo!

Implementación

#1-2 Aceptamos una matriz de Observables y debemos devolver Observables de orden superior con .

Ok, solo una huella de nuestra función futura:

enlace de fragmento

Dado que tenemos arrayOfObservables (nuestros observables ajax), así que repasemos y agreguemos la lógica solicitada:

#3 Agregando efectos secundarios a los observables de argumentos y calculando el porcentaje.

Esto es lo que tenemos:

enlace de fragmento

Agregaremos más funcionalidad a los observables de argumentos en matriz. Iteramos sobre una matriz y aplicamos el operador de finalización para cada observable.

finalizar el operador espera hasta que se complete un observable específico, luego calcula el porcentaje de observables completados y emite un valor con porcentaje Subject Sujeto.

#4 Llamemos a forkJoin para obtener un valor de resultado final

snipper link

Ok, repasemos este código:
forkJoin obtiene una matriz de argumentos observables, se suscribe a todos ellos y espera hasta que se completen.
Una vez que el resultado está listo, el operador de toque emite el último valor porcentual (100%) y completa el porcentaje Subject Sujeto (para evitar fugas de memoria).
Los resultados finales se emitirán a los abonados.

5 Empaquetar toda esta función en’diferir’

La función diferir de RxJS proporciona una nueva instancia observable (un resultado de su función de devolución de llamada) para cada suscriptor. Esto significa que cada uno de nuestros suscriptores obtendrá una ejecución limpia (y contador = 0).

enlace de fragmento

Revisemos cómo funciona:

  1. Obtenemos una matriz de observables (línea 1).
  2. Ajustar el resultado con RxJS diferir para proporcionar una ejecución limpia para cada suscriptor (línea 3)
  3. Crear contador para calcular el porcentaje de finalización y el porcentaje de creación de instancias Subject Sujeto al valor de porcentaje de emisión (líneas 5-6).
  4. Creamos una nueva matriz iterando sobre la matriz original y agregando una nueva funcionalidad con el valor de porcentaje de cálculo final y emitiéndolo si se completan algunos de los observables. (líneas 8-15)
  5. Llame a Rx forkJoin y aplique el operador tap para poder enviar porcentaje 100 cuando forkJoin obtenga un resultado final. Asignar resultado a la variable finalResult variable (líneas 17-22).
  6. Devuelve observable de orden superior que emitirá .

Para terminar

Así es como funciona en un codepen:

forkJoinWithPercent

¿Qué hay de usarlo en Angular?Enlace a esta sección

Esta función también se publica como un paquete npm-rxjs-toolbox para que pueda usarla en sus proyectos.

Y aquí hay una demostración angular de Stackblitz que usa ese paquete para alimentar el valor porcentual para cargar la barra:

En Angular

lectura Adicional.

Puede leer más sobre los casos de uso de operadores RxJS aquí:

  1. «Reintent vs Repeat»
  2. «RxJS: Managing Operator State» de Nicholas Jamieson.
  3. «Operador repetido de RxJS-guía de nigromantes para principiantes»
  4. «Notificaciones de limitación de múltiples usuarios con RxJS»
  5. rxjs-toolkit – Operadores personalizados diarios de RxJS de Jason Awbrey.
  6. backoff – rxjs-Una colección de operadores RxJS útiles para lidiar con estrategias de backoff por Alex Okrushko.

¿Te gusta este artículo? ¡Mantengámonos en contacto en Twitter!

A partir de la sección 4 de mi curso de video de RxJS, se revisa al personal de avances, por lo que si ya está familiarizado con RxJS, también puede encontrar algo útil para usted: observables de orden superior, anti — patrones, planificadores, pruebas unitarias, etc. ¡Inténtalo!

* Un agradecimiento especial a Lars Gyrup Brink Nielsen, Nicholas Jamieson, Tim Deschryver y Michael Karén por revisar este post y hacer muchos comentarios valiosos para mejorarlo.

Discuta con la comunidad

Deja una respuesta

Tu dirección de correo electrónico no será publicada.