带数组的 SwitchMap 运算符

2024-01-27

我正在尝试学习 rxjs 和 Observable 的一般概念,并且有一个场景,我有一类<Room>{} where <Player>{}可以以多对多关系方式加入。

在 Firestore 我收集了rooms每个房间都有一个名为players这是一个用户数组uids.

创建房间组件后,我订阅_roomService.getPlayersInRoom(roomId)如下所示:

getPlayersInRoom(roomId: string) {
  return this._db.doc<Room>(`rooms/${roomId}`).valueChanges().pipe(
    map(room => room.players),
    switchMap(players => players),//2
    switchMap(playerId => {
      if(playerId) {
        return this._db.doc<Player>(`users/${playerId}`).valueChanges();
      }
    })
  );
}

我稍后订阅它

.subscribe(player => {
    if (player) {
      this.players = new Array();
      this.players.push(player);
    }

这里有几个问题。我的可观察对象没有按预期返回玩家数组(请参见 //2 行,它将 string[] 转换为字符串)

另一个问题是我新了this.players每次房间发生变化时我的组件中的数组(否则.push()将推入重复项。

我已经阅读了有关其中一些运算符的文档,并且对它们有所了解,但不足以弄清楚为什么这段代码没有按照应有的方式运行。


First, switchMap期望你返回一个 Observable。如果它是一个类似数组的值 - 它将使用以下命令将其转换为数组from(看这个from example https://thinkrx.io/rxjs/from/).

如果你真的想在流中返回一个数组 - 你应该返回一个流,例如使用of https://thinkrx.io/rxjs/of/: switchMap(value => of([]))

然而,就您而言,您希望用流替换数组中的每个 id。我们需要使用一个combineLatest操作员 https://thinkrx.io/rxjs/combineLatest/,例如(这个名字不言而喻)。我们将把每个玩家阵列切换到一个新的流。我们将在这个新流中结合最新的值valueChanges()溪流。

这是一个例子:

getPlayersInRoom(roomId: string) {
    return this._db.doc<Room>(`rooms/${roomId}`).valueChanges().pipe(
      map(room => room.players),
      switchMap(players => {
        // turn array of player IDs
        // into array of streams of changes
        const playersStreams = players.map(
          playerId => this._db.doc<Player>(`users/${playerId}`).valueChanges()
        );

        // combine latest changes from all streams in that array
        return combineLatest(...playersStreams);
      })
    );
  }

然后在订阅中players将是组合值的数组valueChanges().

getPlayersInRoom(5)
  .subscribe(players => {
    this.players = players;
  })

请注意,还有更多方法可以合并多个值valueChanges()。最常见的是:forkJoin and zip

并且还有更多方法可以将值映射到流上 https://thinkrx.io/gist/ba116f84fe9f1493b989902c0927bb35

希望这可以帮助

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带数组的 SwitchMap 运算符 的相关文章