这种情况是这样的:我有“任务服务”返回了可观察到的任务数组:
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();
}
问题是,这不是很好的关注点分离。查看器组件不应处理所有这些业务逻辑。我想将类型从Mission(从远程服务器返回)中的类型转换为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!
});
}
A,当我转到组件以读取treeHandlerService.Nodes(异步更新的数组)时,它仍然是未定义的(意味着asynchronos活动尚未完成)。
另一个版本是缩短版本,我试图立即返回该值:
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>'.
类型'任务'不能分配给类型'任务[]'。 类型“任务”中缺少属性“长度”。
请帮助大家...
答案 0 :(得分:0)
您可以这样做:
// Don't forget to import the operators
import {map, flatMap, toArray} from 'rxjs/operators';
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 { id: mission.key, label: mission.Title };
}),
toArray() // this will group the nodes into an array of nodes
)
.subscribe((nodes: Node[]) => {
this.nodes = nodes;
});
答案 1 :(得分:0)
我认为可以这样进一步简化:
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
方法,而是简单地使用Rxjs的toArray
运算符和map
方法,而不是另外使用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;
});
}
...
}
运算符有需要的人。
然后在您的组件类中:
var managedContext: NSManagedObjectContext!
let fetchRequest : NSFetchRequest<TrackInfo> = TrackInfo.fetchRequest()
fetchResults = try! managedContext.fetch(fetchRequest)
for (i, _) in Global.Vars.numberOfTrackButtons! {
let workingTrackInfo = fetchResults.randomElement()!
print("current track is: \(workingTrackInfo)")