This is a simplification of a complex case, where some observables in array could be filtered if the values are not valid. The problem is that the filtered observable is not allowing to the other complete the combine. What operator or approach could handle this case allowing the valid data log in the subscription?
// RxJS v6+
import { fromEvent, combineLatest, of } from 'rxjs';
import { mapTo, startWith, scan, tap, map, filter } from 'rxjs/operators';
const userData$ = [
of({ name: 'Joseph', age: 23}),
of({ name: 'Mario', age: 33}),
of({ name: 'Robert', age: 24}),
of({ name: 'Alonso', age: 25})
];
const names = ['Joseph', 'Mario', 'Robert', 'Alonso'];
combineLatest(
names.map((name, i) => {
return userData$[i].pipe(
map(({name, age})=> { return{ name, age: age * 2} }),
filter(({age}) => age < 67),
map(({name, age})=> { return{ name: name.toLocaleUpperCase(), age} }),
)
})
)
.pipe(
tap(console.log),
)
.subscribe();
If we change the value to 67 all the observables will show the data.
A typical problem with combineLatest
is that it requires all source Observables to emit at least once so if you use filter
to discard its only value then combineLatest
will never emit anything.
An easy solution is to make sure it always emits with defaultIfEmpty
:
combineLatest(
names.map((name, i) => {
return userData$[i].pipe(
map(({name, age})=> { return { name, age: age * 2} }),
filter(({age}) => age < 66),
map(({name, age})=> { return { name: name.toLocaleUpperCase(), age} }),
defaultIfEmpty(null),
)
})
)
Live demo: https://stackblitz.com/edit/typescript-rsffbs?file=index.ts
If your real use-case uses other source Observable than of()
that doesn't complete immediatelly you might want to use startWith
instead.