typescript - Combinando múltiples observables y actuando cuando se devuelve al menos un valor en Angular
Tengo un conjunto de observables y necesitaré reaccionar cuando el último haya proporcionado un valor (cualquiera que sea ese).
Mi primer enfoque fue forkJoin así.
const observables = [
this.backend.config(),
this.navigation.location()
];
forkJoin(observables)
.subscribe(([backend, selection]) => {
console.log(backend);
console.log(selection);
});
Esto funcionó parcialmente siempre que los observables emitan complete en algún momento (momento en el que se invoca la finalización). Luego intenté combineLatest. Eso resolvió el problema original pero creó uno nuevo. Ahora, obtengo que se invoca el método final tan pronto como cualquiera de los observables proporciona.
Me gustaría que se invocara cuando cada uno de los observables haya proporcionado al menos una vez y pueda o no haber completado. No importa si es el valor más reciente de cada uno o si es el primero. Aunque, podría ser un plus aprender cómo controlar eso también para +1.
La mejor, aunque improvisada, solución que se me ocurrió es verificar !!backend y !!navigation y actuar solo si todos ellos se cumplen. Estoy buscando una solución más fluida o la confirmación de que la que estoy usando es lo mejor que se puede conseguir.
combineLatest(observables)
.subscribe(([a, b, c]) => {
if (!a || !b || !c)
console.log("Oh, I'm coming...");
else
console.log("Wham, bam - I'm done!");
});
Todo eso de blogs como este o aquel, publicaciones en SO y la documentación de Observables.
Respuesta #1
Bueno, describes al operador correcto:
combineLatestno emitirá un valor inicial hasta que cada observable emita al menos un valor
Entonces creo que tu problema es diferente, ¿quizás algunas de tus fuentes emiten un valor nulo/indefinido?
ref https://www.learnrxjs.io/operators/combination/combinelatest.html
Respuesta #2
Usa zip en lugar de forkJoin. Funciona de manera similar pero no requiere que los observables se completen.
const a$ = of('a'); // will complete instantly
const b$ = timer(2000).pipe(mapTo('b')); // will complete later
const c$ = new BehaviorSubject('c'); // will never complete
zip(a$, b$, c$).subscribe(console.log) // (after 2s) ['a', 'b', 'c']
demo: https://stackblitz.com/edit/rxjs-ycqqhn
