Alexandr Alexandr - 8 days ago 5
AngularJS Question

what triggered combineLatest?

I have a few observables. And I need to know which one triggered the subscribe.

Observable.combineLatest(
this.tournamentsService.getUpcoming(),
this.favoriteService.getFavoriteTournaments(),
this.teamsService.getTeamRanking(),
(tournament, favorite, team) => {
//what triggered combinelatest to run?
}).subscribe()

Answer

Short answer is: You don't know. You could implement some workaround, however this is really ugly and I would recommend rethinking the usecase why you need this and maybe if you can change the architecture. Also keep in mind, that the first execution of your function will be after all three observables have emitted at least 1 value.

Anyway - a possible workaround could be:

let trigger = "";
Observable.combineLatest(
      this.tournamentsService.getUpcoming().do(() => trigger = "tournament"),
      this.favoriteService.getFavoriteTournaments().do(() => trigger = "favTournament"),
      this.teamsService.getTeamRanking().do(() => trigger = "teamRanking"),
(tournament, favorite, team) => {
   console.log(`triggered by ${trigger}`);
}).subscribe();

If you want to execute a specific operation based on which observable triggered, you should make use of each observable and utilize them as individual triggers, that switch to a combined trigger, it might be slightly more code but it is much cleaner and you will not end up in an ugly if/else, switch/case-mess with some hacky workarounds - plus you will have even have the oportunity to use the async-pipe instead of manually subscribing to everything and updating local variables (which is a bad practice anyways):

Here is some example code of how this could look like:

let upcoming$ = this.tournamentsService.getUpcoming();
let favorite$ = this.favoriteService.getFavoriteTournaments();
let rankings$ = this.teamsService.getTeamRanking();

let allData$ = Observable.combineLatest(
    upcoming$, favorite$, rankings$,
    (tournament, favorite, team) => {
        return {tournament, favorite, team};
    }
);

// initial call -> this SHOULD be redundant,
// but since I don't know your code in detail
// i've put this in - if you can remove it or not
// depends on the order your data coming in
allData$
    .take(1)
    .do(({tournament, favorite, team}) => {
        this.displayMatches(...);
        this.sortByFavorites(...);
        this.fillWithRanking(...);
    })
    .subscribe();

// individual update triggers
upcoming$
    .switchMapTo(allData$.take(1))
    .do(({tournament, favorite, team}) => this.displayMatches(...))
    .subscribe();

favorite$
    .switchMapTo(allData$.take(1))
    .do(({tournament, favorite, team}) => this.sortByFavorites(...))
    .subscribe();

rankings$
    .switchMapTo(allData$.take(1))
    .do(({tournament, favorite, team}) => this.fillWithRanking(...))
    .subscribe();
Comments