Ситуация такая: у меня "служба миссии", возвращающая наблюдаемый массив Миссии:
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();
}
Проблема в том, что это не хорошее разделение интересов. Компонент средства просмотра не должен иметь дело со всей этой бизнес-логикой. Я хочу отделить приведение типа Миссия (возвращаясь с удаленного сервера), чтобы ввести Узел в другой сервис.
Как я могу сделать это асинхронно?
Редактировать после предложений по реализации:
Я все еще делаю что-то не так. У меня есть две версии метода getNodes в treeHandlerService, как предложено. Первый - с предложенной имплантацией @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>'.
Тип «Миссия» нельзя назначить типу «Миссия []».
Свойство «длина» отсутствует в типе «Миссия».
Пожалуйста, помогите, ребята ...