带数组的SwitchMap运算符 [英] SwitchMap operator with an array

查看:101
本文介绍了带数组的SwitchMap运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试一般性地学习rxjs和Observable概念,并有一种情况,我有一个<Room>{}类,其中<Player>{}可以加入多对多关系样式.

I'm trying to learn rxjs and the Observable concept in general and have a scenario where I have a class of <Room>{} where <Player>{} can join in many-to-many relationship style.

在Firestore中,我有rooms的集合,其中每个房间都有一个名为players的属性,该属性是用户uid s的数组.

In Firestore I have collection of rooms where each room has a property called players which is an array of user uids.

创建房间组件后,我将订阅_roomService.getPlayersInRoom(roomId),其外观如下:

When a rooms component is created I subscribe to _roomService.getPlayersInRoom(roomId) which looks like below:

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将字符串[]转换为字符串的行)

There are couple of issues here. My observable does not return an array of players as expected (see line //2 which transforms the string[] into a string)

另一个问题是,每次空间发生变化时,我都会在组件中新建this.players数组(否则,.push()会推送重复项.

Another issues is that I new up the this.players array in my component every time that room changes (otherwise the .push() will push in duplicates.

我已经阅读了其中一些运算符的文档,并且对它们有一定的了解,但不足以弄清楚为什么这些代码不符合应有的方式.

I've read documentation on some of these operators and I understand them somewhat but not enough to figure out why this code is not behaving the way it should.

推荐答案

首先,switchMap希望您返回一个Observable.如果它是类似数组的值,它将使用from将其转换为数组(请参见以下 from示例).

First, switchMap expects you to return an Observable. If its an array-like value — it will turn it into an array using from (see this from example).

如果您真的想让数组返回流,则应返回一个流,例如使用 of :switchMap(value => of([]))

If you really want to get an array back on the stream — you should return a stream, e.g. using of: switchMap(value => of([]))

但是,在您的情况下,您想用流替换数组中的每个id.例如,我们将需要使用 combineLatest运算符(名称不言而喻).每个玩家阵列都将切换到一个新的流.这个新的流将结合valueChanges()流上的最新值.

Yet, in your case, you want to substitute each id in the array with a stream. We'll need to use a combineLatest operator, for example (the name speaks for itself). Each array of players we will switch to a new stream. This new stream we'll combine of latest values on valueChanges() streams.

这里有个例子:

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()的组合值的数组.

Then in the subscription players would be an array of combined values from valueChanges().

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

请注意,还有更多的方式可以合并多个valueChanges()中的值.最常见的是:forkJoinzip

Please, note that there are more ways to merge values from multiple valueChanges(). Most common are: forkJoin and zip

还有更多方法在流上映射值

希望这会有所帮助

这篇关于带数组的SwitchMap运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆