使用RxJS v6很难从子集合中检索循环中每个项目的数据。无法迭代从HTTP调用检索的throw数组。合并映射仅对需要在所有数组项目上执行的单个项目执行此操作。
我已经坚持了3天。我已经尝试了一切。问题在于,新的管道语法在为您提供组织代码的巧妙方法的同时,没有简单的方法来循环引发数据收集。无法使用地图javascript函数,因为它在可观察范围之外并且返回的项目不确定。在互联网上,我只能找到一个很好的单个mergeMap的基本示例。但是我需要使用 带有http调用的数组中的每个项目,并将响应附加到同一对象。
我从无法控制的第三方的两个端点开始。我嘲笑了一些示例API来说明。
端点1-返回所有项目ID: http://localhost:3000/contact
{
"name": "test",
"contact": [
{
"_id": "5c9dda9aca9c171d6ba4b87e"
},
{
"_id": "5c9ddb82ca9c171d6ba4b87f"
},
{
"_id": "5c9ddb8aca9c171d6ba4b880"
}
]
}
端点2-返回单个项目信息: http://localhost:3000/contact/5c9dda9aca9c171d6ba4b87e
[
{
"_id": "5c9dda9aca9c171d6ba4b87e",
"firstName": "Luke",
"lastName": "Test",
"email": "vgadgf@adsgasdg.com",
"created_date": "2019-03-29T08:43:06.344Z"
}
]
期望的结果-通过使用RxJs v6 +返回可观察到的嵌套数据:
{
"name": "test",
"contact": [
{
"_id": "5c9dda9aca9c171d6ba4b87e".
"relationship": {
"_id": "5c9dda9aca9c171d6ba4b87e",
"firstName": "Luke",
"lastName": "Test",
"email": "vgadgf@adsgasdg.com",
"created_date": "2019-03-29T08:43:06.344Z"
}
},
{
"_id": "5c9ddb82ca9c171d6ba4b87f",
"relationship": {
"_id": "5c9ddb82ca9c171d6ba4b87f",
"firstName": "Name2",
"lastName": "Test2",
"email": "vgadgf@adsgasdg2.com",
"created_date": "2019-03-29T08:43:06.344Z"
}
},
{
"_id": "5c9ddb8aca9c171d6ba4b880",
"relationship": {
"_id": "5c9ddb8aca9c171d6ba4b880",
"firstName": "Name3",
"lastName": "Test3",
"email": "vgadgf@adsgasdg3.com",
"created_date": "2019-03-29T08:43:06.344Z"
}
}
]
}
当尝试使用Javascript循环时,我只是遇到错误,而使用不同的运算符也不能给我太多,因为RxJ中的循环存在问题。这是我产生的代码。请提供任何有用的建议或文档。
testService.service.ts
import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {concatMap, map, mergeMap} from 'rxjs/operators';
@Injectable()
export class TestServiceService {
constructor(
private http: HttpClient
) { }
public getCombinedData(): Observable<any> {
return this.getMultipleRelationData()
.pipe(
map((result: any) => {
result = result.contact;
return result;
}),
mergeMap((fullResults: any) => {
return fullResults[0].relationship = this.getSingleData(fullResults[0]._id);
})
);
}
public getSingleData(id): Observable<any> {
return this.http.get('http://localhost:3000/contact/' + id);
}
public getMultipleRelationData(): Observable<any> {
return this.http.get('http://localhost:3000/contact');
}
}
我当前的最终数据看起来只是一个项目。如果我只想打一个电话,那就太好了...但是,它与上述所需的输出相差甚远。
[
{
"_id": "5c9dda9aca9c171d6ba4b87e",
"firstName": "Luke",
"lastName": "Test",
"email": "vgadgf@adsgasdg.com",
"__v": 0,
"created_date": "2019-03-29T08:43:06.344Z"
}
]
答案 0 :(得分:2)
使用嵌套的mergeMap
和map
很有可能。坚持使用Observable的一种关键方法是使用from
函数将Contacts数组扩展为Observable。然后,您使用toArray
运算符收集数据。提供记录的示例:
public getCombinedData(): Observable<any> {
return this.getMultipleRelationData()
.pipe(
mergeMap((result: any) =>
// `from` emits each contact separately
from(result.contact).pipe(
// load each contact
mergeMap(
contact => this.getSignleData(contact._id),
// in result selector, connect fetched detail data
(original, detail) => ({...original, relationship: detail})
),
// collect all contacts into an array
toArray(),
// add the newly fetched data to original result
map(contact => ({ ...result, contact})),
)
),
);
}
答案 1 :(得分:0)
尽管kvetis的答案可以为您解决,但这是我实现的,只是发布它是因为我觉得解决起来很有趣。
public getCombinedData(): Observable<any> {
return this.getMultipleRelationData()
.pipe(
mergeMap((result: any) => {
let allIds = result.contact.map(id => this.getSingleData(id._id));
return forkJoin(...allIds).pipe(
map((idDataArray) => {
result.contact.forEach((eachContact, index) => {
eachContact.relationship = idDataArray[index];
})
return result;
})
)
})
);
}
这是您问题的示例解决方案,我制作了虚拟的Observables。 https://stackblitz.com/edit/angular-tonn5q?file=src%2Fapp%2Fapi-calls.service.ts