在订阅方法中构建父子对象
Building Parent Child object inside subscribe method
我有一个 Angular 组件,它订阅了一个由 Angular 服务返回的可观察对象。
组件:
help.component.ts
import { WikiService } from '../../../services/wiki.service';
import { WikiTree } from '../../../interfaces/WikiTree';
export class HelpComponent implements OnInit {
wikiTree$: Observable<WikiTree>
wikiChildTree$: Observable<WikiTree>
public infoCards: Array<Object>;
constructor(private wikiService: WikiService) {}
ngOnInit() {
this.wikiTree$ = this.wikiService.GetWikiHierarchy();
this.wikiTree$.subscribe((data)=>{
const newInfoCards = data.page.results.map(result => (
{
"image": "",
"title": result.title,
"titleLink": "/page/wiki/"+ result.id,
"children": [] /*TODO: Populate this array with a Service call based on result.id*/
}))
this.infoCards = [...this.infoCards,...newInfoCards]
},
(err) => {
console.log(err);
}
);
}
wikiTree$
Observable 具有以下JSON,转换为 TypeScript:
{
"page": {
"results": [
{
"id": "123456789",
"type": "page",
"status": "current",
"title": "Start here",
"extensions": {
"position": 0
},
"_links": {
"webui": "/display/MYSPACE/Start+here",
"edit": "/pages/resumedraft.action?draftId=123456789",
"tinyui": "/x/BQD2Mw",
"self": "https://wiki.abc.com/rest/api/content/123456789"
},
"_expandable": {
"container": "/rest/api/space/MYSPACE",
"metadata": "",
"operations": "",
"children": "/rest/api/content/123456789/child",
"restrictions": "/rest/api/content/123456789/restriction/byOperation",
"history": "/rest/api/content/123456789/history",
"ancestors": "",
"body": "",
"version": "",
"descendants": "/rest/api/content/123456789/descendant",
"space": "/rest/api/space/MYSPACE"
}
},
{
"id": "567890123",
"type": "page",
"status": "current",
"title": "FAQ",
"extensions": {
"position": 1
},
"_links": {
"webui": "/display/MYSPACE/FAQ",
"edit": "/pages/resumedraft.action?draftId=567890123",
"tinyui": "/x/HQD2Mw",
"self": "https://wiki.abc.com/rest/api/content/567890123"
},
"_expandable": {
"container": "/rest/api/space/MYSPACE",
"metadata": "",
"operations": "",
"children": "/rest/api/content/567890123/child",
"restrictions": "/rest/api/content/567890123/restriction/byOperation",
"history": "/rest/api/content/567890123/history",
"ancestors": "",
"body": "",
"version": "",
"descendants": "/rest/api/content/567890123/descendant",
"space": "/rest/api/space/MYSPACE"
}
}
],
"start": 0,
"limit": 25,
"size": 2,
"_links": {
"self": "https://wiki.abc.com/rest/api/content/998877665/child/page"
}
},
"_links": {
"base": "https://wiki.abc.com",
"context": "",
"self": "https://wiki.abc.com/rest/api/content/998877665/child"
},
"_expandable": {
"attachment": "/rest/api/content/998877665/child/attachment",
"comment": "/rest/api/content/998877665/child/comment"
}
}
打字稿:WikiTree.ts
export interface WikiTree {
page: Page;
_links: Links;
_expandable: Expandable;
}
export interface Page {
results?: (ResultsEntity)[] | null;
start: number;
limit: number;
size: number;
_links: Links1;
}
export interface ResultsEntity {
id: string;
type: string;
status: string;
title: string;
extensions: Extensions;
_links: Links2;
_expandable: Expandable1;
}
export interface Extensions {
position: number;
}
export interface Links2 {
webui: string;
edit: string;
tinyui: string;
self: string;
}
export interface Expandable1 {
container: string;
metadata: string;
operations: string;
children: string;
restrictions: string;
history: string;
ancestors: string;
body: string;
version: string;
descendants: string;
space: string;
}
export interface Links1 {
self: string;
}
export interface Links {
base: string;
context: string;
self: string;
}
export interface Expandable {
attachment: string;
comment: string;
}
我想通过调用基于其父项的服务来填充 children
数组 result.id
例如:调用将是 Wiki 服务中的一个函数,returns 一个可观察对象。
this.wikiChildTree$ = this.wikiService.GetWikiHierarchy(result.id);
根据 wikiChildTree$
observable 中返回的数据,我想创建一个 title
和 link
对象的数组。因此,infoCards
对象数组将反映一个 JSON 对象,如下所示:
[{
"image": "",
"title": "Start here",
"titleLink": "/page/wiki/123456789",
"children": [{
"title": "Storm",
"link": "/page/wiki/660431"
},
{
"title": "Weather",
"link": "/page/wiki/660432"
}]
},
{
"image": "",
"title": "FAQ",
"titleLink": "/page/wiki/567890123",
"children": [{
"title": "Cloud",
"link": "/page/wiki/450433"
},
{
"title": "Sunshine",
"link": "/page/wiki/120432"
}]
}
]
这就像进行父子异步调用,以获取子数据。
我已经阅读了 forkjoin 和 mergemap,但不确定这里的实现。我怎么做?
所以基本上你应该可以这样做:
ngOnInit() {
this.wikiTree$ = this.wikiService.GetWikiHierarchy().pipe(
switchMap(data =>
forkJoin(data.page.results.map(result => this.wikiService.GetWikiHierarchy(result.id))).pipe(
map(children => ({data, children}))
)
)
).subscribe(({data, children}) => {
const newInfoCards = data.page.results.map((result, i) => (
{
"image": "",
"title": result.title,
"titleLink": "/page/wiki/"+ result.id,
"children": children[i]
}))
this.infoCards = [...this.infoCards,...newInfoCards]
},
(err) => {
console.log(err);
}
);
}
说明:
- 你加载this.wikiService.GetWikiHierarchy();
- 您使用 同时为每个 结果 加载所有 this.wikiService.GetWikiHierarchy(result.id) forkJoin.
- 您将两个地方的加载数据映射到 object {data, children} where data - 第一次调用的结果 children - 第二个 forkJoin 的结果(children 或 child[][ 的数组]).
- 之后你需要加入 data.page.results 和 children(这是数组的数组) .
希望对您有所帮助。
向 Amir 的回答添加了 return 数据以消除错误。 map 函数需要 return 一个 wikiTree 类型的可观察对象。
ngOnInit() {
this.wikiTree$ = this.wikiService.GetWikiHierarchy().pipe(
switchMap(data =>
forkJoin(data.page.results.map(result => this.wikiService.GetWikiHierarchy(result.id))).pipe(
map(children => ({data, children}))
)
)
).subscribe((data, children) => {
const newInfoCards = data.page.results.map((result, i) => (
{
"image": "",
"title": result.title,
"titleLink": "/page/wiki/"+ result.id,
"children": children[i]
}))
this.infoCards = [...this.infoCards,...newInfoCards]
return data
},
(err) => {
console.log(err);
}
);
}
我有一个 Angular 组件,它订阅了一个由 Angular 服务返回的可观察对象。
组件: help.component.ts
import { WikiService } from '../../../services/wiki.service';
import { WikiTree } from '../../../interfaces/WikiTree';
export class HelpComponent implements OnInit {
wikiTree$: Observable<WikiTree>
wikiChildTree$: Observable<WikiTree>
public infoCards: Array<Object>;
constructor(private wikiService: WikiService) {}
ngOnInit() {
this.wikiTree$ = this.wikiService.GetWikiHierarchy();
this.wikiTree$.subscribe((data)=>{
const newInfoCards = data.page.results.map(result => (
{
"image": "",
"title": result.title,
"titleLink": "/page/wiki/"+ result.id,
"children": [] /*TODO: Populate this array with a Service call based on result.id*/
}))
this.infoCards = [...this.infoCards,...newInfoCards]
},
(err) => {
console.log(err);
}
);
}
wikiTree$
Observable 具有以下JSON,转换为 TypeScript:
{
"page": {
"results": [
{
"id": "123456789",
"type": "page",
"status": "current",
"title": "Start here",
"extensions": {
"position": 0
},
"_links": {
"webui": "/display/MYSPACE/Start+here",
"edit": "/pages/resumedraft.action?draftId=123456789",
"tinyui": "/x/BQD2Mw",
"self": "https://wiki.abc.com/rest/api/content/123456789"
},
"_expandable": {
"container": "/rest/api/space/MYSPACE",
"metadata": "",
"operations": "",
"children": "/rest/api/content/123456789/child",
"restrictions": "/rest/api/content/123456789/restriction/byOperation",
"history": "/rest/api/content/123456789/history",
"ancestors": "",
"body": "",
"version": "",
"descendants": "/rest/api/content/123456789/descendant",
"space": "/rest/api/space/MYSPACE"
}
},
{
"id": "567890123",
"type": "page",
"status": "current",
"title": "FAQ",
"extensions": {
"position": 1
},
"_links": {
"webui": "/display/MYSPACE/FAQ",
"edit": "/pages/resumedraft.action?draftId=567890123",
"tinyui": "/x/HQD2Mw",
"self": "https://wiki.abc.com/rest/api/content/567890123"
},
"_expandable": {
"container": "/rest/api/space/MYSPACE",
"metadata": "",
"operations": "",
"children": "/rest/api/content/567890123/child",
"restrictions": "/rest/api/content/567890123/restriction/byOperation",
"history": "/rest/api/content/567890123/history",
"ancestors": "",
"body": "",
"version": "",
"descendants": "/rest/api/content/567890123/descendant",
"space": "/rest/api/space/MYSPACE"
}
}
],
"start": 0,
"limit": 25,
"size": 2,
"_links": {
"self": "https://wiki.abc.com/rest/api/content/998877665/child/page"
}
},
"_links": {
"base": "https://wiki.abc.com",
"context": "",
"self": "https://wiki.abc.com/rest/api/content/998877665/child"
},
"_expandable": {
"attachment": "/rest/api/content/998877665/child/attachment",
"comment": "/rest/api/content/998877665/child/comment"
}
}
打字稿:WikiTree.ts
export interface WikiTree {
page: Page;
_links: Links;
_expandable: Expandable;
}
export interface Page {
results?: (ResultsEntity)[] | null;
start: number;
limit: number;
size: number;
_links: Links1;
}
export interface ResultsEntity {
id: string;
type: string;
status: string;
title: string;
extensions: Extensions;
_links: Links2;
_expandable: Expandable1;
}
export interface Extensions {
position: number;
}
export interface Links2 {
webui: string;
edit: string;
tinyui: string;
self: string;
}
export interface Expandable1 {
container: string;
metadata: string;
operations: string;
children: string;
restrictions: string;
history: string;
ancestors: string;
body: string;
version: string;
descendants: string;
space: string;
}
export interface Links1 {
self: string;
}
export interface Links {
base: string;
context: string;
self: string;
}
export interface Expandable {
attachment: string;
comment: string;
}
我想通过调用基于其父项的服务来填充 children
数组 result.id
例如:调用将是 Wiki 服务中的一个函数,returns 一个可观察对象。
this.wikiChildTree$ = this.wikiService.GetWikiHierarchy(result.id);
根据 wikiChildTree$
observable 中返回的数据,我想创建一个 title
和 link
对象的数组。因此,infoCards
对象数组将反映一个 JSON 对象,如下所示:
[{
"image": "",
"title": "Start here",
"titleLink": "/page/wiki/123456789",
"children": [{
"title": "Storm",
"link": "/page/wiki/660431"
},
{
"title": "Weather",
"link": "/page/wiki/660432"
}]
},
{
"image": "",
"title": "FAQ",
"titleLink": "/page/wiki/567890123",
"children": [{
"title": "Cloud",
"link": "/page/wiki/450433"
},
{
"title": "Sunshine",
"link": "/page/wiki/120432"
}]
}
]
这就像进行父子异步调用,以获取子数据。
我已经阅读了 forkjoin 和 mergemap,但不确定这里的实现。我怎么做?
所以基本上你应该可以这样做:
ngOnInit() {
this.wikiTree$ = this.wikiService.GetWikiHierarchy().pipe(
switchMap(data =>
forkJoin(data.page.results.map(result => this.wikiService.GetWikiHierarchy(result.id))).pipe(
map(children => ({data, children}))
)
)
).subscribe(({data, children}) => {
const newInfoCards = data.page.results.map((result, i) => (
{
"image": "",
"title": result.title,
"titleLink": "/page/wiki/"+ result.id,
"children": children[i]
}))
this.infoCards = [...this.infoCards,...newInfoCards]
},
(err) => {
console.log(err);
}
);
}
说明:
- 你加载this.wikiService.GetWikiHierarchy();
- 您使用 同时为每个 结果 加载所有 this.wikiService.GetWikiHierarchy(result.id) forkJoin.
- 您将两个地方的加载数据映射到 object {data, children} where data - 第一次调用的结果 children - 第二个 forkJoin 的结果(children 或 child[][ 的数组]).
- 之后你需要加入 data.page.results 和 children(这是数组的数组) . 希望对您有所帮助。
向 Amir 的回答添加了 return 数据以消除错误。 map 函数需要 return 一个 wikiTree 类型的可观察对象。
ngOnInit() {
this.wikiTree$ = this.wikiService.GetWikiHierarchy().pipe(
switchMap(data =>
forkJoin(data.page.results.map(result => this.wikiService.GetWikiHierarchy(result.id))).pipe(
map(children => ({data, children}))
)
)
).subscribe((data, children) => {
const newInfoCards = data.page.results.map((result, i) => (
{
"image": "",
"title": result.title,
"titleLink": "/page/wiki/"+ result.id,
"children": children[i]
}))
this.infoCards = [...this.infoCards,...newInfoCards]
return data
},
(err) => {
console.log(err);
}
);
}