【问题标题】:How to populate observable with another observable and return observable如何用另一个 observable 填充 observable 并返回 observable
【发布时间】:2019-04-20 23:06:21
【问题描述】:

我正在开发 rxjs 项目,我正在使用 json-server 作为数据库提供程序。我一直在获取一个需要用另一个集合填充的集合。

我有收藏Match和收藏Tournament。 在集合 Match 中,我只有tournamentId,但我的类 Match 还包含 Tournament 实例。

class Match{
    id:number;
    ...
    tournamentId:number;
    tournament: Tournament;
}

class Tournament{
    id:number;
    ...
    name:String;
}

我需要来自 db 的 2 个调用。首先获得所有锦标赛,然后获得所有比赛。

我需要返回已填充锦标赛的 Match Observable

get(): Observable<Match> {
    return Observable.create(obs => {
      tournamentService.get().pipe(toArray()).subscribe(tournaments => {//tournaments = [torunament1, tournament2]
        super.get().pipe(map(x => { let m = new Match(x); m.populateTournament(tournaments); obs.next(m); return m; })).subscribe(() => {
          obs.complete();
        });
      });
    });
  }

obs.complete() 被立即调用,因此我最终只创建了一个可观察的匹配项。 我正在尝试在地图管道中填充 Match with Tournament,并将其作为 obs.next(m) 发送到那里。我也不知道这算不算聪明。

tournamentService.get()super.get() 分别返回 Tournamentunpopulated Match 的 Observables (具有相同属性的 JS {object})。

我如何将 next() 一个一个匹配,然后将它们全部发送给订阅者调用 complete()?

【问题讨论】:

    标签: typescript rxjs observable


    【解决方案1】:

    您不应该创建自己的 observables,您已经可以使用现有的操作符。我认为 mergeMap、switchMap 和 combineLatest 都可以在这里工作。

    你应该结合这两个 observables:

      get(): Observable<Match> {
        return combineLatest([super.get(), tournamentService.get()]) // Combine both Observables when both emit
          .pipe(map(([match, tours])=> { // Destructuring array of emitted values
            let m = new Match(match);
            m.populateTournament(tours);
            return m; // Return match combined with tournaments
        }))
      }
    

    【讨论】:

    • 确认!但是还是有问题。锦标赛是可观察的,只发出一次(它是整个锦标赛数组),因为我的 populateTournament() 方法中需要所有锦标赛。
    • 那么问题出在哪里?您将获得所有这样的锦标赛。
    • 左 observable 比右 observable 发射更多的次数。留下了 super.get()。比赛服务.get().pipe(toArray()) 是对的。因为我不需要一场一场的比赛,所以我需要他们全部排列。
    • 我想说的是 combineLatest 受到发射较少的 observable 的限制。由于一个 observable 是整个数组(发出一次),因此其他 observable 受到限制,并且只发出最新的(例如第 15 个匹配项)。
    • 用 withLatestFrom 管道管理它。
    【解决方案2】:

    我也设法解决了“withLatestFrom”管道的问题。

     get(): Observable<Match> {
        let matchesObs = super.get();
        let tournamentsObs = tournamentService.get().pipe(toArray());
    
        return matchesObs.pipe(
          withLatestFrom(tournamentsObs),
          map(([m, t]) => {
            let match = new Match(m as Match);
            match.populateTournament(t as Tournament[]);
            return match;
          })
        );
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-05
      • 1970-01-01
      • 2018-11-21
      • 2020-10-10
      • 2017-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多