rxjs:嵌套的http请求

时间:2018-09-17 14:42:49

标签: typescript rxjs

我需要一些有关嵌套Observable的串联/管道化/分组的解释。

我有一个远程API / foo / bars / 100 ,该API会回复以下json对象

{ 
    id: 100,
    members: [{memberID: 1},..,{{memberID: N}]
}

我还有另一个API / members / $ {id} ,该API返回以下json:

{
    id: ${id}
    values: ['bla bla bla',...]
}

我想调用( GET )api / foo / bars / 100 ,然后遍历成员,并为每个成员调用( GET / members / $ {id} ,然后构建结果对象。

我想获得以下结果:

{
    id: 100,
    members: [
        {
            memberID: 1,
            data: {
                id: 1,
                values: ['bla bla bla', ...],
            }
        },
        {
            memberID: 100,
            data: {
                id: 100,
                values: ['bla bla bla', ...]
            }
        }
    ]
}

获得结果的最佳实践是什么?

3 个答案:

答案 0 :(得分:1)

这是我的解决方案。 它按预期工作。

您有什么改进建议吗?

 return dataService.getFooBars(100)
    .pipe(
        mergeMap((item) => {
            const members = _.map(item.members, member => {
                return  dataService.getMemberByID(member.memberID)
                    .pipe(
                        map((memberData) => {
                            member.data = memberData;
                            return member;
                        })
                    );
            });

            return forkJoin(...members).pipe(
                map(members => {
                    item.members = members;
                    return item;
                })
            );
        })
    )

答案 1 :(得分:0)

如果您希望一次加载所有成员的数据,则可以在成员加载后使用forkJoin。您也可以使用Promise.all()

答案 2 :(得分:0)

我只是自己学习RxJS的可观察性,并且我很乐意将您的问题作为个人练习来处理。我尚未对此进行测试,但是我认为这应该非常接近您如何以线性,功能化的方式将输入数据转换为所需的输出方式:

const fooBarID = 100;
const membersObservable
    // { id: 100, members: [ {memberID: 1}, ..., {memberID: N} ] }
    = dataService.getFooBars(fooBarID)
        .pipe(
            // => [ {memberID: 1}, ..., {memberID: N} ]
            map(response => response.members),
            // => [ 1, ..., N ]
            map(listOfObjs => listOfObjs.map(obj => obj.memberID),
            // => [ Observable<APIMember>(1), ..., Observable<APIMember>(N) ]
            map(memberIDs => memberIDs.map(
                memberID => dataService.getMemberByID(memberID)
            )),
            // => Observable<APIMember[]>
            switchMap(memberObservables => forkJoin(...memberObservables)),
            // => [ Member(1), ..., Member(N) ]
            map(apiMembers => apiMembers.map(
                apiMember => ({ memberID: apiMember.id, data: apiMember })
            )),
            // => { id: 100, members: [ Member(1), ..., Member(N) ] }
            map(members => ({ id: fooBarID, members }))
        );

如果您尝试一下,我很乐意听取您关于它是如何工作(或失败)的信息。