Angular 在订阅之前,如何使用另一个请求循环http响应,扩展初始响应?

Angular 在订阅之前,如何使用另一个请求循环http响应,扩展初始响应?,angular,rxjs,Angular,Rxjs,我正在使用Angular 6,我需要扩展从Http请求获得的联系人数组。每个联系人都有一个用户ID。我需要遍历contacts数组,根据userId发出另一个请求,这样我就可以使用用户的名字和姓氏扩展每个联系人。我必须提到,我必须在订阅之前完成它 contacts.service.ts findContacts(params: paramsModel): Observable<resultsModel> { const httpParams = this.getParams(

我正在使用Angular 6,我需要扩展从Http请求获得的联系人数组。每个联系人都有一个用户ID。我需要遍历contacts数组,根据userId发出另一个请求,这样我就可以使用用户的名字和姓氏扩展每个联系人。我必须提到,我必须在订阅之前完成它

contacts.service.ts

findContacts(params: paramsModel): Observable<resultsModel> {
    const httpParams = this.getParams(params);

    return this.http.get<resultsModel>('/getAllContacts', {
        params: httpParams
    }).pipe(
        map((res: any) => res),
        switchMap(res => {
            const requests = res.map(contact => {
                return this.http.get<any>('getUserById?userId=' + contact.userId).pipe(
                    map(userData => {
                        console.log(userData);
                        return _.extend(contact, {
                                            userFirstName: user.firstName,
                                            userLastName: user.lastName
                                });
                    })
                );
            });
            return forkJoin(requests);
        }),
        map( res => {
            return someFunction(res, params);
        })
    );
}
findContacts(参数:paramsModel):可观察{
const httpParams=this.getParams(params);
返回此.http.get(“/getAllContacts”{
参数:httpParams
}).烟斗(
映射((res:any)=>{
//在这里,我获得了所有联系人,但我需要遍历每个联系人,并根据userId发出另一个请求,以获取属于每个联系人的用户的信息
//res看起来像这样:
// {
//     [
//id:1,
//名称:test1,
//用户ID:14
//     ],
//     [
//id:2,
//名称:test2,
//用户ID:9
//     ],
//     ..
// }
//我需要把它扩展成这样:
// {
//     [
//id:1,
//名称:test1,
//用户ID:14,
//用户名:约翰,
//userLastName:Doe,
//     ],
//     [
//id:2,
//名称:test2,
//用户ID:9,
//用户名:Jane,
//userLastName:Doe,
//     ],
//     ..
// }
//我尝试了很多方法,但都不走运(包括flatMap、switchMap、使用链接观察对象,但在订阅之前我没有找到一个可以复制的循环示例,所以我很快就迷路了)。
//这是其中之一:
//res.map(联系人=>{
//this.http.get('getUserById?userId='+contact.userId).pipe(
//映射(用户=>{
////使用下划线进行扩展
//_uu.延伸(联系{
//userFirstName:user.firstName,
//userLastName:user.lastName
//             });
//回接;
//         })
//     );
// });
返回一些函数(res、params);
})
);
}
contacts.data.ts

导出类联系人数据扩展数据{
构造函数(专用联系人服务:联系人服务){
超级();
}
负载触点(
params:paramsModel
) {
this.loadingSubject.next(true);
this.contactsService.findContacts(params).pipe(
轻触(res=>{
this.entitySubject.next(res.items);
this.paginatorTotalSubject.next(res.totalCount);
}),
catchError(err=>of(新结果模型([],err)),
完成(()=>this.loadingSubject.next(false))
).subscribe();
}
}
contacts-list.component.ts

导出类ContactsListComponent实现OnInit{
contactsData:contactsData;
恩戈尼尼特(){
const params=new paramsModel();
此.contactsData.loadContacts(参数);
}
}
解决方案在MichałTkaczyk的帮助下:

contacts.service.ts

findContacts(params: paramsModel): Observable<resultsModel> {
    const httpParams = this.getParams(params);

    return this.http.get<resultsModel>('/getAllContacts', {
        params: httpParams
    }).pipe(
        map((res: any) => res),
        switchMap(res => {
            const requests = res.map(contact => {
                return this.http.get<any>('getUserById?userId=' + contact.userId).pipe(
                    map(userData => {
                        console.log(userData);
                        return _.extend(contact, {
                                            userFirstName: user.firstName,
                                            userLastName: user.lastName
                                });
                    })
                );
            });
            return forkJoin(requests);
        }),
        map( res => {
            return someFunction(res, params);
        })
    );
}
findContacts(参数:paramsModel):可观察{
const httpParams=this.getParams(params);
返回此.http.get(“/getAllContacts”{
参数:httpParams
}).烟斗(
映射((res:any)=>res),
开关映射(res=>{
const requests=res.map(contact=>{
返回此.http.get('getUserById?userId='+contact.userId).pipe(
映射(userData=>{
console.log(userData);
返回扩展(联系{
userFirstName:user.firstName,
userLastName:user.lastName
});
})
);
});
返回forkJoin(请求);
}),
地图(res=>{
返回一些函数(res、params);
})
);
}

首先将rxjs映射更改为switchMap,然后您可以迭代第一个可观察的数据,并创建一个可观察的数组,该数组可以在switchMap中作为forkJoin返回

代码:

您可以尝试这段代码,虽然我不建议创建这么多请求,但更好的方法是从API调用获取这些数据

编辑:

正如Oles Savluk所提到的,switchMap中的resultSelector已被弃用,因此您可以在forkJoin中的每个可见项添加另一个管道:

switchMap(res => {
  const requests = res.map(contact => {
    return this.http.get<any>('getUserById?userId=' + contact.userId).pipe(
      map(userData => {
        return { ...contact, ...userData };
      })
    );
  });

  return forkJoin(requests);
})
switchMap(res=>{
const requests=res.map(contact=>{
返回此.http.get('getUserById?userId='+contact.userId).pipe(
映射(userData=>{
返回{…联系人,…用户数据};
})
);
});
返回forkJoin(请求);
})

获取所有联系人->将联系人映射到可观察的联系人->它发出每个项目->使用每个项目形成一个http请求->在该http请求上,通过管道映射来获取格式结果,使用联系人和用户详细信息->使用toArray()将其收集为数组->订阅。返回所需输出的数组

    this.http.get<resultsModel>('/getAllContacts', { params: httpParams}).pipe(
     mergeMap(contacts=> from(contacts)),
     concatMap((contact) =>  this.http.get<any>('getUserById?userId=' + contact.userId).pipe(
                           map((userDetails) => {
                                  contact['userFirstName']=userDetails['userFirstName'];
                                  contact['userLastName']=userDetails['userLastName'];
                                 return contact
                                }))),
     toArray()).subscribe(res => console.log(res));
this.http.get('/getAllContacts',{params:httpParams}).pipe(
合并映射(联系人=>from(联系人)),
concatMap((contact)=>this.http.get('getUserById?userId='+contact.userId).管道(
地图((用户详细信息)=>{
联系人['userFirstName']=userDetails['userFirstName'];
    this.http.get<resultsModel>('/getAllContacts', { params: httpParams}).pipe(
     mergeMap(contacts=> from(contacts)),
     concatMap((contact) =>  this.http.get<any>('getUserById?userId=' + contact.userId).pipe(
                           map((userDetails) => {
                                  contact['userFirstName']=userDetails['userFirstName'];
                                  contact['userLastName']=userDetails['userLastName'];
                                 return contact
                                }))),
     toArray()).subscribe(res => console.log(res));