2016-11-25 30 views
2

我有一些觀察。我需要知道哪一個觸發了訂閱。什麼觸發combineLatest?

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

訂閱observable就像調用函數一樣。 – Manish

+0

好的,但沒有回答我的問題。 – Alexandr

回答

3

簡短的回答是:你不知道。 你可以實現一些解決方法,但是這真的很醜,我會建議重新考慮用例,爲什麼你需要這個,也許如果你可以改變架構。還請記住,函數的第一次執行將在所有三個觀測值發出至少一個值之後進行。

反正 - 一個可能的解決方法可能是:

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/else,switch/case-mess與一些hacky解決方法結束 - 加上您甚至可以使用oportunity async - 管道而不是手動訂閱所有內容並更新局部變量(反正這是一個不好的做法):

下面是如何可能看起來像一些示例代碼:

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

嘿,謝謝你的回覆。 那就是我現在的解決方法:) 我還沒有找到更好的解決方案。 是的,我需要開始時他們三個人的結果。 – Alexandr

+0

我很好奇 - 你爲什麼需要這個? – olsn

+0

我有3個火力點觀測: -get即將開始的比賽 -GET喜愛 -get排名 它加載我應該顯示的比賽,通過收藏夾來分類的第一次,並且充滿了排名。 - 如果比賽更新,我只想求助他們 - 如果最喜歡更新,我會根據他們的最愛使用他們。 ---如果積分榜正在改變,我不會訴諸它,但我只會更新這場比賽的排名。 – Alexandr

2

您可以使用scan運營商發出的值與任何先前發出的值進行比較,並可能包括額外的數據表明與否組件組合的觀察值實際上已經改變。例如:

let combined = Observable 
    .combineLatest(
    this.tournamentsService.getUpcoming(), 
    this.favoriteService.getFavoriteTournaments(), 
    this.teamsService.getTeamRanking() 
) 
    .scan((acc, values) => [ 
    ...values, 
    acc[0] !== values[0], 
    acc[1] !== values[1], 
    acc[2] !== values[2] 
    ], []); 

combined.subscribe(
    ([tournament, favorite, team, tournamentChanged, favoriteChanged, teamChanged]) => { 
    console.log(`tournament = ${tournament}; changed = ${tournamentChanged}`); 
    console.log(`favorite = ${favorite}; changed = ${favoriteChanged}`); 
    console.log(`team = ${team}; changed = ${teamChanged}`); 
    } 
); 
1

甲相當乾淨的實現,這是通過使用時間戳操作者http://reactivex.io/documentation/operators/timestamp.html

實施例代碼

sourceObservable 
    .pipe(
    timestamp(), // wraps the source items in object with timestamp of emit 
    combineLatest(otherObservable.pipe(timestamp()), function(source, other) { 

     if(source.timestamp > other.timestamp) { 

     // source emitted and triggered combineLatest 
     return source.value; 
     } 
     else { 

     // other emitted and triggered combineLatest 
     return other.value; 
     } 

    }), 
) 

如果兩個以上的可觀察參與「RX」三通按照時間戳對combineLatest()進行排序可以檢測哪一個觸發了combineLatest()