angular - 将 observable 返回的对象数组转换为另一种类型的数组
问题描述
情况是这样的:我有“任务服务”返回一个可观察的任务数组:
getMissions(): Observable<Mission[]> {
return this.http.get<Mission[]>(this.MissionUrl).pipe(
tap(_ => this.log('Fetched missions.')),
catchError(this.handleError('getMissions: ', []))
);
以及组件内这个完美运行的订阅者功能:
export class TreeViewerComponent implements OnInit {
missions: Mission[];
Nodes: Node[]=[];
Edges: Edge[];
constructor(private missionService: MissionService,
private messageService: MessageService) { }
ngOnInit() {
this.getNodes();
}
getNodes(): void {
this.missionService.getMissions()
.subscribe(missions => {
this.missions = missions;
this.doThis();
})
}
doThis(): void{
console.log('tree-viewer component1: '+this.missions);
for (var i=0;i<this.missions.length;i++)
{
var tempNode= {id: this.missions[i].key, label: this.missions[i].Title};
console.log(tempNode);
this.Nodes.push(tempNode);
}
this.getEdges();
this.wrapData();
}
问题是,它不是一个很好的关注点分离。查看器组件不应该处理所有这些业务逻辑。我想将类型转换与任务类型(从远程服务器返回)分开,以将 Node 类型输入另一个服务。
我怎样才能做到异步?
实施建议后编辑:
我仍然在做错事。正如建议的那样,我在 treeHandlerService 中有两个版本的 getNodes 方法。第一个是 @fmontes 建议的实施,它确实有效:
getNodes(): void
{
this.missionService
.getMissions()
.pipe(
flatMap((missions: Mission[]) => missions), // this will pass each mission to the map
map((mission: Mission) => { // this will turn each Mission into a Node
return new Node(mission.key, mission.Title) ;
}),
toArray() // this will group the nodes into an array of nodes
)
.subscribe((nodes: Node[]) => {
this.Nodes = nodes;
this.log('nodes: '+this.Nodes[0].label);//the log shows that it is working!
});
}
唉,当我去组件读取treeHandlerService.Nodes(异步更新的数组)时,它仍然是未定义的(意味着异步活动还没有完成)。
另一个版本是缩短版本,我尝试立即返回该值:
getNodes(): Observable<Node[]> {
return this.missionService.getMissions().pipe(
map((mission: Mission) => { // this will turn each Mission into a Node
return new Node(mission.key, mission.Title) ;
}),
toArray()
)
};
但它甚至没有编译!我收到以下错误:
ERROR in src/app/tree-handler.service.ts(39,7): error TS2345: Argument of type 'OperatorFunction<Mission, Node>' is not assignable to parameter of type 'OperatorFunction<Mission[], Node>'.
类型“任务”不能分配给类型“任务 []”。“任务”类型中缺少属性“长度”。
请帮助各位...
解决方案
我认为它可以像这样进一步简化:
import { map, catchError } from 'rxjs/operators';
export class MissionService {
...
getMissions(): Observable < Mission[] > {
return this.http.get < Mission[] > (this.MissionUrl).pipe(
map(missions => missions.map(mission => ({
id: mission.key,
label: mission.Title })
)),
catchError(this.handleError('getMissions: ', []))
);
}
...
}
在这里,我没有额外使用flatMap
andtoArray
运算符,而是简单地使用map
Rxjs 的运算符和map
数组上的方法来完成必要的操作。
然后在您的组件类中:
export class TreeViewerComponent implements OnInit {
missions: Mission[];
Nodes: Node[] = [];
Edges: Edge[];
constructor(
private missionService: MissionService,
private messageService: MessageService
) {}
...
getNodes(): void {
this.missionService.getMissions()
.subscribe(missions => {
this.missions = missions;
});
}
...
}
推荐阅读
- html - 带背景的 CSS 箭头
- tensorflow - “LookupError:梯度注册表没有条目:shap_TensorListStack”使用 DeepExplainer for Keras 模型
- java - 尝试制作一个自动自定义对话框
- wpf - MVVM 灯。当属性的值真正改变时执行方法的正确方法
- c# - 何将参数从 orchstrator 传递到活动函数
- flutter - 在 CustomScrollView 颤动中检测 DragEnd?
- python - AttributeError:模块“google.cloud.vision”没有属性“类型”
- datetime - FFMpeg - 在像监控一样的录制过程中打印日期和时间
- api - Find NiFi Remote Process Group 通过其 Rest API 启用或禁用
- javascript - 用户点击提交后不显示提示信息