Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS Combine 2 Subscriptions

I have a service that outputs 2 observables. 1 is for just getting the currently authenticated user and the other is for getting all of the active users. On the main screen I want to call both of these observables to use, this will be done (currently) by subscribing to both of these observables, however the first observable does not always run. I am looking for a solution for both observables to emit a value before anything errors our or loads on the page. I have tried forkjoin in my examble below but it does not work, i suspect this is because forkjoin expects something to emit but nothing emits, but subscribing to both observables does output the data I need. here is what I have tried:

    const tt =  Observable.forkJoin(
        this.auth.getActiveUsers().map((res) => res = res  ),
        this.auth.user.map((res) => res = res ),        
    );
    console.log("running" ); 
    tt.subscribe( (data) => {
      console.log("data ", data );      
        console.log("data[0] ", data[0] );
        console.log("data[1] ", data[1] );        
      },
      err => console.error(err),
      () => console.error("complete"),
    );  

and here is how the subscriptions are laid out in my service.ts file:

    Filename: Service.ts

    ...

    // first Observable  
    constructor( private afAuth: AngularFireAuth,
                private db: AngularFirestore ) {

        this.user = this.afAuth.authState.switchMap(user => {
            if (user) {
                return this.db.doc<iUser>(`users/${user.uid}`).valueChanges()
            } else {
                return Observable.of(null)
            }
            })     

    }

    ...

    // second Observable
    getActiveUsers(): Observable<iUser[]> {
    return this.db.collection<iUser>('users').valueChanges().catch(this.catchError);                 
    }

    ...
like image 399
Kravitz Avatar asked Oct 29 '22 20:10

Kravitz


2 Answers

forkJoin expects an array, so I think that's why it didn't work in your code:

 const tt = Observable.forkJoin([
                this.auth.getActiveUsers(),
                this.auth.user
            ]);
 // ...
like image 138
sebaferreras Avatar answered Nov 15 '22 07:11

sebaferreras


I guess your auth.user observable is a hot one (not complete when the value is emitted) while forkJoin emits only when all passed observables are complete. Not emit a value but complete.

If my guess is correct what you can do in this case is just passing auth.user.first() which will create a complete observable from the original observable and your forkJoin will work as expected

like image 43
smnbbrv Avatar answered Nov 15 '22 07:11

smnbbrv