带数组的SwitchMap运算符 [英] SwitchMap operator with an array
问题描述
我正在尝试一般性地学习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 uid
s.
创建房间组件后,我将订阅_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()
中的值.最常见的是:forkJoin
和zip
Please, note that there are more ways to merge values from multiple valueChanges()
. Most common are: forkJoin
and zip
还有更多方法在流上映射值
希望这会有所帮助
这篇关于带数组的SwitchMap运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!