【问题标题】:Handling parallel nested observables in RxJS在 RxJS 中处理并行嵌套的 observables
【发布时间】:2020-04-22 10:00:01
【问题描述】:

我正在清理项目中嵌套的并行可观察对象,但在处理可观察事件时遇到了一些问题。这是我的音乐应用程序中的一种情况,我加载播放列表页面并需要加载播放列表数据、有关用户的信息以及用户是否正在关注播放列表:


  • Route Observable (returns参数从URL,我需要提取playlistId)
    • Playlist Observable(需要playlistId返回 PlaylistObject 并解决)
    • 用户可观察(返回 UserObject
      • IsUserFollowing Observable(如果用户关注播放列表,则需要 playlistIdUserObject.id返回 T/F)

总之,我从 Angular 的 Route observable 接收到路由参数,我需要并行触发另外两个 observable,Playlist ObservableUser Observable。一旦播放列表数据返回,Playlist Observable 可以解析,但User Observable 需要继续到另一个可观察对象IsFollowingUser,直到它可以解析。

这是我当前(糟糕的)嵌套可观察对象的实现:

this.route.params.pipe(
  first()
).subscribe((params: Params) => {

  this.playlistId = parseInt(params["playlistId"]);

  if (this.playlistId) {

    this.playlistGQL.watch({ 
      id: this.playlistId,
    }).valueChanges.pipe(
      takeUntil(this.ngUnsubscribe)
    ).subscribe((response) => { 
      this.playlist = response; // use this to display playlist information on HTML page
      this.playlistTracks = response.tracks; //loads tracks into child component
    });

    this.auth.user$.pipe(
      filter(stream => stream != null)
    ).subscribe((user) => {
      this.user = user;
      this.userService.isFollowingPlaylist(this.user.id, this.playlistId).subscribe((response) => {
        this.following = response; //returns a T/F value that I use to display a follow button
      })
    })

  }

这可行,但显然不遵循 RxJS 最佳实践。像这样清理嵌套的并行可观察对象的最佳方法是什么?

【问题讨论】:

    标签: javascript angular rxjs


    【解决方案1】:

    这是我会做的事情,虽然这可能不是最理想的,但可能比以前更好。

    我假设前面的代码块在ngOnInit 中。

    async ngOnInit() {
      // get the params as if it is a promise
      const params: Params = await this.route.params.pipe(
                                          first()
                                        ).toPromise();
    
      this.playlistId = parseInt(params["playlistId"]);
      if (this.playlistId) {
        // can name these functions to whatever you like (better names)
        this.reactToPlaylistGQL();
        this.reactToUser();
      }
    }
    
    private reactToPlaylistGQL() {
      this.playListGQL.watch({
        id: this.playListId,
      }).valueChanges.pipe(
       takeUntil(this.ngUnsubscribe)
     ).subscribe(response => {
       this.playlist = response;
       this.playlistTracks = response.tracks;
     });
    }
    
    private reactToUser() {
      this.auth.user$.pipe(
        filter(stream => stream != null),
        // switch over to the isFollowingPlaylist observable
        switchMap(user => {
         this.user = user;
         return this.userService.isFollowingPlaylist(this.user.id, this.playListId);
       }),
        // consider putting a takeUntil or something of that like to unsubscribe from this stream
      ).subscribe(response => this.following = response);
    }
    

    我发现将 if (this.playlistId) 块中的函数命名为人类友好的名称使得不必编写 cmets(描述性函数名称说明它应该做什么)并且看起来比放置一个 RxJS 流的 blob 更干净。

    我都是徒手写的,所以可能有一些错别字。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-10
      • 2017-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      相关资源
      最近更新 更多