代码之家  ›  专栏  ›  技术社区  ›  Henry

将可观测数据从一个动态的可观测数组组合成一个可观测数据?

  •  1
  • Henry  · 技术社区  · 6 年前

    总结:本质上我需要 from Users where usergroupIds in [1,3,5] .

    鉴于 usergroupIds$ 发出组ID数组 [1,3,5]

    我想通过以下方式联合所有用户 userids 在里面 usergroupIds 并组合用户ID(distinct)

    我想到的是:

    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
    

    取消订阅&重新订阅 users$ 每次换衣服都是错的?

    可以表达吗 用户$ 完全在RXJS中,而不是每次都在订阅中创建它?

    更新: 在@fancheung的帮助下:

    combinedUsers$ = userGroupIds$.pipe(
            switchMap(userGroupIds => {
                const users$s = userGroupIds.map(groupId =>
                    createUsersObservable(groupId))
                return combineLatest(...users$s)
            })
    

    但是,由于usersobservable一次发出一组用户,combinedUsers$会导致类似 [[userA, userB], [userB, userC], [userA, userD]] 我不介意对订阅进行额外处理:

    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
        })
    

    然而,有没有一种方法可以用某种方式使 combinedUsers$ ,然后执行 distinct 操作员?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Fan Cheung    6 年前

    看看这是否有效。基本上,它在usergroupids$发出时触发,这样您就可以看到新的动态。 shareReplay 如果你总是希望源是可观测的,就需要 usergroupdIds$ 在订阅时发出上次保存的值

    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)
        )
    })
    )
    
        2
  •  0
  •   martin    6 年前

    所以你不想单独向 createUsersObservable 每一次 usergroupIds$ 发射。这听起来像是一个很好的用例 mergeScan :

    usergroupIds$.pipe(
      mergeScan((users, user) => createUsersObservable().pipe(
        map(user => [user, ...users]),
      ), []),
    );
    

    现场演示: https://stackblitz.com/edit/rxjs-8zybdu

    推荐文章