josh_in_dc
josh_in_dc

Reputation: 119

How to sequence multiple observables

I'm new to Angular2 and front-end development in general, so my apologies if I'm missing the obvious answer.

I'm working on an Angular2 app. I'm not sure about the best way to accomplish a task in a component I'm working on.

ngOnInit() {
    console.log("init component");
    console.log(this.activatedRoute);

    this.paramSub = this.activatedRoute.params.switchMap(
        (params: Params) => this.personSearchService.getPerson(params['personId']))
        .subscribe(result => this.personDetails = result);

    this.orgSub = this.personSearchService.getPersonFedOrgs(0).subscribe(
        results => this.orgs = results,
        error => console.log(error)
    );

    //pseudo-code
    watch this.orgs and this.personDetails
        if change
            do logic
}

During the OnInit lifecyle hook, I do two things, I get and use a route parameter with a service and I also get a list of organizations from a second service. All of that's working fine.

The section I've labeled as psuedo-code is functionality I want to add. I want to take the results of the first two service calls and execute some business logic.

I know that I can't directly use this.personDetails and this.orgs because they'll be undefined (until the async calls are resolved). So I think I need to wrap them in an Observable so that I can execute some logic each time they're updated. But I'm not exactly sure how to do that. Any pointers in the right direction would be greatly appreciated.

Upvotes: 1

Views: 765

Answers (2)

Milad
Milad

Reputation: 28592

CombineLatest does the job , except , it would emit a value if either of the streams has emitted any value , so you can't be sure that you get notified when both of them have actually emitted values .

For this , you need to zip them :d

    this.paramSub = this.activatedRoute.params.switchMap(
        (params: Params) => this.personSearchService.getPerson(params['personId']));

    this.orgSub = this.personSearchService.getPersonFedOrgs(0)


Observable.zip(this.paramSub, this.orgSub)
  .subscribe(result) => {
    console.log(result);
  })

Upvotes: 0

Sasxa
Sasxa

Reputation: 41264

You can use cobmineLatest() operator. I refactored the code a bit for readability:

personDetails$ = this.activatedRoute.params
  .map((params: Params) => params['personId'])
  .switchMap(id => this.personSearchService.getPerson(id))

orgs$ = this.personSearchService.getPersonFedOrgs(0)

Observable.combineLatest(personDetails$, orgs$)
  .subscribe(([details, orgs]) => {
    console.log(details, orgs);
  })

Don't forget to import operator:

import 'rxjs/add/observable/combineLatest';

Upvotes: 1

Related Questions