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(); 

Sample in stackblitz

If we change the value to 67 all the observables will show the data.

2 Answers

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:

If your real use-case uses other source Observable than of() that doesn't complete immediatelly you might want to use startWith instead.

You can replace combineLatest with from as combineLatest won't emit if either one of the item in stream array doesn't emit

const userData$ = [ { name: 'Joseph', age: 23 }, { name: 'Mario', age: 33 }, { name: 'Robert', age: 24 }, { name: 'Alonso', age: 25 } ]; const names = ['Joseph', 'Mario', 'Robert', 'Alonso']; from( userData$ ) .pipe( map(({ name, age }) => { return { name, age: age * 2 } }), filter(({ age }) => age < 66), map(({ name, age }) => { return { name: name.toLocaleUpperCase(), age } }), tap(console.log), ) .subscribe(); 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.