【问题标题】:Modify Observable array before subscribing by rxjs operators在 rxjs 操作符订阅之前修改 Observable 数组
【发布时间】:2021-12-31 21:04:59
【问题描述】:

有两个模型如下所示:

export class Game {
 id: number;
 name: string;
 platform: number;
}

export class Platform {
 id: number;
 name: string;
}

拥有一个可观察的 Game 对象数组,该数组具有与 Platform 对象相关的 platformId 属性。为了更好地理解,我创建了两种单独的方法来获取我的游戏列表和另一种方法来获取基于 id 的平台。

getGames(): Observable<Game[]> {
    return of([
      {
        id: 1,
        name: 'god of war',
        platform: 1,
      },
      {
        id: 2,
        name: 'halo',
        platform: 2,
      },
    ]);
  }

  getPlatform(id): Observable<Platform> {
    if (id === 1)
      return of({
        id: 1,
        name: 'ps4',
      });

    if (id === 2)
      return of({
        id: 2,
        name: 'xbox',
      });
  }

现在我在 rxjs 的两个运算符 (switchMap,forkJoin) 的帮助下达到了这一点:

this.getGames()
      .pipe(
        switchMap((games: Game[]) =>
          forkJoin(
            games.map((game) =>
              forkJoin([this.getPlatform(game.platform)]).pipe(
                map(([platform]) => ({
                  game: game.name,
                  platform: platform.name,
                }))
              )
            )
          )
        )
      )
      .subscribe((v) => {
        console.log(v);
        this.gamesV2 = v;
      });

和我的最终结果:

 [
     {
      game: "god of war"
      platform: "ps4"
     },
     {
      game: "halo"
      platform: "xbox"
     }
 ]

是否有可能以更简单的方式实现这一目标? StackBlitz

【问题讨论】:

    标签: rxjs observable fork-join switchmap


    【解决方案1】:

    通过扁平化 getPlatformV2 的内部可观察数组:

    this.getGames()
      .pipe(
        switchMap(games =>
          combineLatest(
            games.map(game =>
              this.getPlatformV2(game.id).pipe(
                map(platform => ({
                  game: game.name,
                  platform
                }))
              )
            )
          )
        )
      )
    

    额外:关于游戏和平台,如果您不在它们上实现构造函数,则应该使用 TS 类型或接口而不是类。

    【讨论】:

      【解决方案2】:

      感谢 Daniel Gimenez,我在StackOverflow 中找到了另一种方法并将其放在这里,如果有人有更好更简单的方法,我非常感谢与我分享。 创建另一个返回平台名称的方法:

       getPlatformV2(id): Observable<string> {
          const platforms = [
            {
              id: 1,
              name: 'ps4',
            },
            {
              id: 2,
              name: 'xbox',
            },
          ];
          return of(platforms.find(x=>x.id===id).name);
        }
      }
      

      我没有使用两个 forkjoin,而是使用了 concatMap

      this.getGames()
            .pipe(
              switchMap((games) => games),
              concatMap((game) =>
                forkJoin({
                  game: of(game.name),
                  platform: this.getPlatformV2(game.platform),
                })
              ),
              toArray()
            )
            .subscribe(console.log);
      

      【讨论】:

        猜你喜欢
        • 2021-07-26
        • 2023-03-23
        • 1970-01-01
        • 2020-10-07
        • 1970-01-01
        • 2018-03-13
        • 1970-01-01
        • 2016-07-07
        • 1970-01-01
        相关资源
        最近更新 更多