Observable 中每个 id 的循环数组和 return 数据
Loop array and return data for each id in Observable
使用 RxJS v6 从循环中的每个项目的子集合中检索数据具有挑战性。无法迭代从 HTTP 调用中检索到的抛出数组。合并映射仅对需要对所有数组项执行此操作的单个项执行此操作。
我已经坚持了 3 天了。我已经尝试了一切。问题是新的管道语法虽然为您提供了组织代码的简洁方法,但没有简单的方法来循环抛出数据集合。无法使用 map javascript 函数,因为它在可观察范围之外并且项目 returned 未定义。在互联网上,我只能找到一个效果很好的单个 mergeMap 的基本示例。但是我需要使用
数组中的每个项目都带有 http 调用并将响应追加到同一对象。
我从第 3 方的两个端点开始,我无法控制它们。我嘲笑了一些例子API来说明。
端点 1 - Returns 所有项目 ID:
http://localhost:3000/联系人
{
"name": "test",
"contact": [
{
"_id": "5c9dda9aca9c171d6ba4b87e"
},
{
"_id": "5c9ddb82ca9c171d6ba4b87f"
},
{
"_id": "5c9ddb8aca9c171d6ba4b880"
}
]
}
端点 2 - Returns 单项信息:
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+ return 嵌套数据可观察:
{
"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 循环时遇到错误,并且使用不同的运算符也没有给我太多帮助,因为问题在于 RxJs 中的循环。这是我制作的代码。请提供任何有用的建议或文档。
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"
}
]
使用嵌套的 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
(original, detail) => ({...original, relationship: detail})
),
// collect all contacts into an array
toArray(),
// add the newly fetched data to original result
map(contact => ({ ...result, contact})),
)
),
);
}
编辑:结果选择器已弃用
里面的mergeMap
,后面可以用一个map
。
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).pipe(
map(detail => ({ ...contact, relationship: detail })),
),
// collect all contacts into an array
toArray(),
// add the newly fetched data to original result
map(contact => ({ ...result, contact })),
),
),
),
);
}
虽然 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;
})
)
})
);
}
这是针对您的问题的示例解决方案,我制作了虚拟 Observable。
https://stackblitz.com/edit/angular-tonn5q?file=src%2Fapp%2Fapi-calls.service.ts
使用 RxJS v6 从循环中的每个项目的子集合中检索数据具有挑战性。无法迭代从 HTTP 调用中检索到的抛出数组。合并映射仅对需要对所有数组项执行此操作的单个项执行此操作。
我已经坚持了 3 天了。我已经尝试了一切。问题是新的管道语法虽然为您提供了组织代码的简洁方法,但没有简单的方法来循环抛出数据集合。无法使用 map javascript 函数,因为它在可观察范围之外并且项目 returned 未定义。在互联网上,我只能找到一个效果很好的单个 mergeMap 的基本示例。但是我需要使用 数组中的每个项目都带有 http 调用并将响应追加到同一对象。
我从第 3 方的两个端点开始,我无法控制它们。我嘲笑了一些例子API来说明。
端点 1 - Returns 所有项目 ID: http://localhost:3000/联系人
{
"name": "test",
"contact": [
{
"_id": "5c9dda9aca9c171d6ba4b87e"
},
{
"_id": "5c9ddb82ca9c171d6ba4b87f"
},
{
"_id": "5c9ddb8aca9c171d6ba4b880"
}
]
}
端点 2 - Returns 单项信息: 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+ return 嵌套数据可观察:
{
"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 循环时遇到错误,并且使用不同的运算符也没有给我太多帮助,因为问题在于 RxJs 中的循环。这是我制作的代码。请提供任何有用的建议或文档。
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"
}
]
使用嵌套的 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
(original, detail) => ({...original, relationship: detail})
),
// collect all contacts into an array
toArray(),
// add the newly fetched data to original result
map(contact => ({ ...result, contact})),
)
),
);
}
编辑:结果选择器已弃用
里面的mergeMap
,后面可以用一个map
。
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).pipe(
map(detail => ({ ...contact, relationship: detail })),
),
// collect all contacts into an array
toArray(),
// add the newly fetched data to original result
map(contact => ({ ...result, contact })),
),
),
),
);
}
虽然 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;
})
)
})
);
}
这是针对您的问题的示例解决方案,我制作了虚拟 Observable。 https://stackblitz.com/edit/angular-tonn5q?file=src%2Fapp%2Fapi-calls.service.ts