我正在尝试学习 rxjs 和 Observable 的一般概念,并且有一个场景,我有一类<Room>{}
where <Player>{}
可以以多对多关系方式加入。
在 Firestore 我收集了rooms
每个房间都有一个名为players
这是一个用户数组uid
s.
创建房间组件后,我订阅_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(使用前将#替换为@)