Summary: essentially I need something like from Users where usergroupIds in [1,3,5]
.
Given usergroupIds$
emit an array of group IDs [1,3,5]
I want to union all users by userids
in usergroupIds
and combine the userIds (distinct)
Here is what I came up with:
usergroupIds$.subscribe(usergroupIds => {
const users$s = usergroupIds.map(gid => createUsersObservable(gid))
// [users$ in group 1, users$ in group 3, users$ in group 5]
const users$ = combineLatest(...user$s).pipe(
distinct(user => user.id)
)
})
createUsersObservable = gid =>
collectionData(db.collection('users').where('groupId', '==', gid)) // rxFire firestore
Unsubscribe & resubscribe users$
every time on change seems wrong?
Is it possible to express users$
fully in RxJS without creating it in a subscription every time?
Update: With help from @FanCheung:
combinedUsers$ = userGroupIds$.pipe(
switchMap(userGroupIds => {
const users$s = userGroupIds.map(groupId =>
createUsersObservable(groupId))
return combineLatest(...users$s)
})
However, since usersObservable emit an array of users at a time, The combinedUsers$ results in somthing like [[userA, userB], [userB, userC], [userA, userD]]
which I don't mind to carry out the extra processing on subscribe:
combinedUsers$.subscribe(combinedUsers => {
const userMap = {}
for (const users of combinedUsers)
users.forEach(user => (userMap[user.id] = user))
const uniqueUsers = Object.values(userMap)
// update UI to uniqueUsers
})
However, is there a way to use somehow flatten the results of combinedUsers$
, and then carry out the distinct
operator?
See if this work. Basically it fires when usergroupIds$ emits and thus you get your new dynamic observable. shareReplay
is needed if you always want the source observable usergroupdIds$
to emit the last saved value when subscribed
usergroupIds$.pipe(
shareReplay(1),
switchMap(usergroupIds => {
const users$Array = usergroupIds.map(gid => createUsersObservable(gid))
// [users$ in group 1, users$ in group 3, users$ in group 5]
return forkJoin(...users$Array).pipe(
map(arr=>[].concat(...arr)),
switchMap(arr=>from(arr)),
distinct(user => user.id)
)
})
)