Ayoub.A
Ayoub.A

Reputation: 2093

Angular: ForkJoin ngrx observables

I have an ngrx store that contains multiple states. I'm trying to construct one object (Rent object) by gathering data from each state: Here is my code:

ngOnInit() {


  //Fetch the rent and its properties data
  const rentID = +this.route.snapshot.params['id'];

  let rentState$ = this.store.select('rentState');
  let clientState$ = this.store.select('clientState');
  let vehiculeState$ = this.store.select('vehiculesState');
  let paymentState$ = of(null);//TODO

  let importRent$ = forkJoin([rentState$, vehiculeState$, clientState$, paymentState$])
    .pipe(mergeMap(([rentData, vehiculeData, clientData, paymentData]: [any, any, any, any]) => {
      let rent = new Rent();

      rent = rentData.rentList.filter(rent => rent.id === rentID)[0];

      rent.vehicule = vehiculeData.vehicules.filter(vehicule => vehicule.id === this.rent.vehicule.id)[0];

      rent.client = clientData.clientList.filter(client => client.id === this.rent.client.id)[0];
      rent.companion = clientData.companionList.filter(companion => companion.id === this.rent.companion.id)[0];

      //TODO: retrieve payments

      return of(rent);
    }))


  importRent$.subscribe(data => console.log('hello'));

}

But I don't get any message 'hello' in my console. For some reason the code the subscription does not happen.

I already have these imports in my code:

import { Observable } from 'rxjs/Observable';
import { forkJoin } from 'rxjs/observable/forkJoin';
import { of } from 'rxjs/observable/of';
import { mergeMap } from 'rxjs/operators';

The store already has data in it. Any idea what am I doing wrong?

Upvotes: 4

Views: 8199

Answers (2)

BBlackwo
BBlackwo

Reputation: 1436

As @martin said in his comment

forkJoin requires all source Observables to complete.

So you just need to take the first value emitted with take(1) or first():

let importRent$ = combineLatest(
  rentState$.pipe(take(1)), 
  vehiculeState$.pipe(take(1)), 
  clientState$.pipe(take(1)), 
  paymentState$.pipe(take(1))
)

Upvotes: 5

Chau Tran
Chau Tran

Reputation: 5088

Are you positive that ALL of the states emit and complete? Try with combineLatest? And I don't think you need to put the observables in an array as a paramter for forkJoin.

While using combineLatest, everytime a child-source Observable emits after the initial emit of all child-source, the whole thing emits. You might wanna look into distinctUntilChanged as well if you don't want over-emitting scenario.

1 emits, 2 emits => combineLatest emits => 1 emits => combineLatest emits etc...

Upvotes: 7

Related Questions