Angular - 如何在数组中映射可观察对象
Angular - how to map observable inside array
我有一个 servers 对象数组,在该数组中我有另一个可观察的对象数组,它的键是 [securityGroups] .
ngOnInit(): void {
forkJoin(
this.serverService.getServer(),
this.securityGroupService.getSecurityGroups())
.pipe(takeWhile(() => this.alive))
.subscribe(([servers, groups]) => {
this.servers = servers.map((item) => ({
...item,
securityGroups: this.serverService.getServerById(item.id)
.pipe(map(server => server["security_groups"]))
}))
this.securityGroupArray = groups['security_groups'].map((item) => ({
...item,
expanded: false,
}))
}
如何从我的服务器阵列映射此 [securityGroup] 密钥?因为它是一个 Observable。我不想在 html 中创建一个异步管道,我想将它保存在一个新数组中
我的服务器阵列负载:
[{id: "1879f47f-1c5e-464b-bb76-e7cc13ef426e", name: "hello", flavor: {…}, securityGroups: Observable}
,
{id: "b9c7e32a-bf99-4250-83cb-13523f9c1604", name: "test01", flavor: {…}, securityGroups: Observable}]
您可以使用 forkJoin
解析所有内部可观察对象并将其映射到 server
对象的 securityGroups
属性
this.serverService.getServer()
.pipe(switchMap((servers) => {
return from(servers).pipe(mergeMap((server) => {
return forkJoin(server.securityGroups)
.pipe(map((_securityGroups) => {
server.securityGroups =_securityGroups
return server;
}))
}))
}))
如果我理解正确,你的挑战是你收到了一个 server
s 数组,你需要为每个数组调用以检索更多数据 (securityGroup
s) 并将其附加到对象。
为此,您需要以某种方式“订阅”此辅助调用,以便接收数据。有几个"Higher Order Mapping Operators" that can do this for you, so you don't have to deal with nested subscriptions. In this case, we can use switchMap
.
为了一次进行一堆调用,我们可以使用 forkJoin
一次进行所有调用并接收所有结果的数组。
您目前正在使用 forkJoin
进行 2 次不同的调用,但您并未将这些调用的结果用于同一目的。我会将它们分成单独的可观察对象,既为了意图的清晰,也为了它们可以独立使用:
securityGroups$ = this.securityGroupService.getSecurityGroups().pipe(
map(groups => groups.map(group => ({
...group,
expanded: false
})))
);
servers$ = this.serverService.getServers().pipe(
switchMap(servers => forkJoin(
servers.map(s => this.serverService.getServerById(s.id))
)
.pipe(
map(serversWithGroups => serversWithGroups.map((server, i) => ({
...servers[i],
securityGroups: server.security_groups
}))),
// shareReplay(1) - see comment below
))
);
如果需要,您仍然可以在控制器中订阅:
ngOnInit() {
this.servers$.subscribe();
this.securityGroups$.subscribe();
}
或者您可以在模板中使用 AsyncPipe
:
<ng-container *ngFor="let group of securityGroups$ | async">
<option *ngFor="let server of servers$ | async" [value]="server.id">
<ng-container *ngFor="let secGroup of server.securityGroups">
{{ secGroup.name !== group.name ? server.name : '' }}
</ng-container>
</option>
</ng-container>
如果您正在嵌套 *ngFor
,那么您可以使用 shareReplay()
运算符来防止多个订阅多次执行您的服务方法。
我有一个 servers 对象数组,在该数组中我有另一个可观察的对象数组,它的键是 [securityGroups] .
ngOnInit(): void {
forkJoin(
this.serverService.getServer(),
this.securityGroupService.getSecurityGroups())
.pipe(takeWhile(() => this.alive))
.subscribe(([servers, groups]) => {
this.servers = servers.map((item) => ({
...item,
securityGroups: this.serverService.getServerById(item.id)
.pipe(map(server => server["security_groups"]))
}))
this.securityGroupArray = groups['security_groups'].map((item) => ({
...item,
expanded: false,
}))
}
如何从我的服务器阵列映射此 [securityGroup] 密钥?因为它是一个 Observable。我不想在 html 中创建一个异步管道,我想将它保存在一个新数组中
我的服务器阵列负载:
[{id: "1879f47f-1c5e-464b-bb76-e7cc13ef426e", name: "hello", flavor: {…}, securityGroups: Observable}
,
{id: "b9c7e32a-bf99-4250-83cb-13523f9c1604", name: "test01", flavor: {…}, securityGroups: Observable}]
您可以使用 forkJoin
解析所有内部可观察对象并将其映射到 server
对象的 securityGroups
属性
this.serverService.getServer()
.pipe(switchMap((servers) => {
return from(servers).pipe(mergeMap((server) => {
return forkJoin(server.securityGroups)
.pipe(map((_securityGroups) => {
server.securityGroups =_securityGroups
return server;
}))
}))
}))
如果我理解正确,你的挑战是你收到了一个 server
s 数组,你需要为每个数组调用以检索更多数据 (securityGroup
s) 并将其附加到对象。
为此,您需要以某种方式“订阅”此辅助调用,以便接收数据。有几个"Higher Order Mapping Operators" that can do this for you, so you don't have to deal with nested subscriptions. In this case, we can use switchMap
.
为了一次进行一堆调用,我们可以使用 forkJoin
一次进行所有调用并接收所有结果的数组。
您目前正在使用 forkJoin
进行 2 次不同的调用,但您并未将这些调用的结果用于同一目的。我会将它们分成单独的可观察对象,既为了意图的清晰,也为了它们可以独立使用:
securityGroups$ = this.securityGroupService.getSecurityGroups().pipe(
map(groups => groups.map(group => ({
...group,
expanded: false
})))
);
servers$ = this.serverService.getServers().pipe(
switchMap(servers => forkJoin(
servers.map(s => this.serverService.getServerById(s.id))
)
.pipe(
map(serversWithGroups => serversWithGroups.map((server, i) => ({
...servers[i],
securityGroups: server.security_groups
}))),
// shareReplay(1) - see comment below
))
);
如果需要,您仍然可以在控制器中订阅:
ngOnInit() {
this.servers$.subscribe();
this.securityGroups$.subscribe();
}
或者您可以在模板中使用 AsyncPipe
:
<ng-container *ngFor="let group of securityGroups$ | async">
<option *ngFor="let server of servers$ | async" [value]="server.id">
<ng-container *ngFor="let secGroup of server.securityGroups">
{{ secGroup.name !== group.name ? server.name : '' }}
</ng-container>
</option>
</ng-container>
如果您正在嵌套 *ngFor
,那么您可以使用 shareReplay()
运算符来防止多个订阅多次执行您的服务方法。