17

私はいくつかの観察対象を持っています。そして、どれがサブスクライブをトリガーしたかを知る必要があります。

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

6 に答える 6

11

簡単な答えは次のとおりです。いくつかの回避策を実装できますが、これは本当に見苦しいので、なぜこれが必要なのか、アーキテクチャを変更できるかどうか、ユースケースを再考することをお勧めします。また、関数の最初の実行は、3 つのオブザーバブルすべてが少なくとも 1 つの値を発行した後であることに注意してください。

とにかく - 考えられる回避策は次のとおりです。

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に終わり、いくつかのハッキーな回避策があります-さらにasync、すべてを手動でサブスクライブしてローカル変数を更新する代わりに、-pipeを使用する機会さえあります(これはとにかく悪い習慣です) :

これがどのように見えるかのコード例を次に示します。

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();
于 2016-11-26T00:31:35.180 に答える
0

これを解決するより良い方法は、判別共用体型を使用することです。言語に識別共用体が組み込まれていない場合は、コンストラクターを非公開にしn、各オブザーバブルに 1 つずつ、null 許容のパブリック静的プロパティを公開することで作成できます。私は C# の方が使いやすいので、これを C# で記述しますが、翻訳は簡単なはずです。null 許容文字列に注意してください。言語が nullables をサポートしていない場合は、他のメカニズムを使用して、値が設定されているかどうかを示します。

private class DiscriminatedUnion
{
    private DiscriminatedUnion(string? property1, string? property2)
    {
        Property1 = property1;
        Property2 = property2;
    }

    public string? Property1 { get; }
    public string? Property2 { get; }

    public static DiscrimintatedUnion FromObservable1(string property1)
    {
        return new DiscriminatedUnion(property1, null);
    }

    public static DiscrimintatedUnion FromObservable2(string property2)
    {
        return new DiscriminatedUnion(null, property2);
    }

}

private IObservable<DiscriminatedUnion> CreateCombination()
{
    var firstObservable = tournamentsService
        .getUpcoming()
        .Select(x => DiscriminatedUnion.FromObservable1(x));

    var secondObservable = favoriteService
        .getFavoriteTournaments()
        .Select(x => DiscriminatedUnion.FromObservable2(x));

    return Observable
        CombineLatest(firstObservable, secondObservable);
}

CreateCombination()これで、observable が値を発行した元の判別共用体に質問できるようになりました。

于 2021-04-16T16:57:09.087 に答える
0
combineLatest([
    this.obs1.pipe(tap(() => (this.trigger = 'obs1'))),
    this.obs2.pipe(tap(() => (this.trigger = 'obs2'))),
])
.subscribe(([obs1, obs2]) => {
    switch (this.trigger) {
        case 'obs1':
            // ...
        case 'obs2':
            // ...
    }
})
于 2021-12-06T13:53:21.497 に答える