在过去,我会定义一个新的Promise
,推迟它,然后在我的功能完成时解决它。
现在我发现自己处于需要从函数返回Observable
的情况,我想确保我在Angular 5
上下文中正确设置它。
测试功能,工作正常:
getTreeViewChildren(currNode: any, nodeType: string, nodeTypeEnum: number = 0, nested: boolean = true)
: Observable<any>
{
let treeObs: Observable<any>;
treeObs = new Observable(obs => {
this.siteConfigService.getHostAccessPoints().subscribe(data => {
let hostAccessPoints = JSON.parse(data);
let accPointTree = this.findChildNodes(currNode, hostAccessPoints, nested);
obs.next(accPointTree);
obs.complete();
});
});
return treeObs;
}
从我的NG组件中我成功订阅了:
this.configService.getTreeViewChildren(this.selectedTreeViewItem, type, nodetype, true).subscribe(tree =>{
let theTree = tree;
});
然而,真正的函数有更多的检索逻辑。根据我上面的测试函数设置Observable
的正确方法是什么?相同的模式,只需将所有代码包装在treeObs = new Observable(..)
?
getTreeViewChildNodes(currNode: any, nodeType: string, nodeTypeEnum: number = 0, nested: boolean = true): Observable<any> {
let hosts;
let locations;
let hostAccessPoints;
let treeResult: Observable<any>;
if (nodeTypeEnum === NodeType.Location) {
// more code..
let someTree = getStuff();
return someTree;
}
if (nodeTypeEnum === NodeType.Host) {
// more code..
let someTree = getStuff();
return someTree;
}
if (nodeTypeEnum === NodeType.HostAccessPoint) {
let accPointTree;
if (sessionStorage["hostAccessPoints"]) {
// more code..
let someTree = getStuff();
return someTree;
}
else {
this.siteConfigService.getHostAccessPoints().subscribe(data => {
// more code..
let someTree = getStuff();
return someTree;
});
}
}
if (nodeTypeEnum === NodeType.HostStorage) {
// TO DO
}
}
****更新(基于Observable.of()
建议的答案):
// Builds hierarchical treeview data
getTreeViewChildNodes(currNode: any, nodeType: string, nodeTypeEnum: number = 0, nested: boolean = true): Observable<any> {
let hosts;
let locations;
let hostAccessPoints;
if (nodeTypeEnum === NodeType.Location) {
if (sessionStorage["locations"] != null && sessionStorage["locations"] != "undefined") {
locations = JSON.parse( sessionStorage.getItem('locations') );
}
// find child nodes
let locationTree = this.findChildren(currNode, locations, nested);
return Observable.of(locationTree);
}
if (nodeTypeEnum === NodeType.Host) {
if (sessionStorage["hosts"] != null && sessionStorage["hosts"] != "undefined") {
hosts = JSON.parse( sessionStorage.getItem('hosts') );
}
// find child hosts for current node
let hostTree = this.findChildHosts(currNode, hosts, nested);
return Observable.of(hostTree);
}
if (nodeTypeEnum === NodeType.HostAccessPoint) {
let accPointTree;
if (sessionStorage["hostAccessPoints"]) {
hostAccessPoints = sessionStorage.getItem("hostAccessPoints");
accPointTree = this.findChildHostAccessPoints(currNode, hostAccessPoints, nested);
return Observable.of(accPointTree);
}
else { // **** THREW ERROR FROM CALLER 'Cannot read property 'subscribe' of undefined****`
/*this.siteConfigService.getHostAccessPoints().subscribe(data => {
hostAccessPoints = JSON.parse(data);
accPointTree = this.findChildHostAccessPoints(currNode, hostAccessPoints, nested);
return Observable.of(accPointTree);
});*/
// ** CORRECTED CODE **
return this.siteConfigService.getHostAccessPoints().map(data => {
hostAccessPoints = JSON.parse(data);
accPointTree = this.findChildHostAccessPoints(currNode, hostAccessPoints, nested);
return accPointTree;
});
}
}
}
从我的组件代码中,它只会在我调用我的服务的地方抛出错误TypeError: Cannot read property 'subscribe' of undefined
,而服务又调用http.get():
this.configService.getTreeViewChildNodes(this.selectedTreeViewItem, type, nodetype, true).subscribe(data => {
this.rebuildNetworkTree(data);
});
答案 0 :(得分:4)
可能你应该使用一个主题,不管这样:
let treeSubj = new Subject<any>();
let treeResult = this.treeSubj.asObservable();
// a lot of code
// need to tick a value in treeResult somewhere - can do this in several places
this.treeSubj.next(yourValue)
// and then somewhere need to get that result
this.treeResult.subscribe(tree => doSomething(tree));
这样,每当您致电treeSubj.next(value)
时,您的treeResult
订阅者都会收到该值。
答案 1 :(得分:3)
我无法衡量你的第二个例子试图返回的详细信息,但是更好的方法是做第一个例子而不是new Observable(...)
。最好只使用map
operator来转换数据。
getTreeViewChildren(currNode: any, nodeType: string, nodeTypeEnum: number = 0, nested: boolean = true): Observable<any> {
return this.siteConfigService.getHostAccessPoints().map(data => {
let hostAccessPoints = JSON.parse(data);
let accPointTree = this.findChildHostAccessPoints(currNode, hostAccessPoints, nested);
return 'test123';
});
}
从评论中更新
如果你有一个有时使用异步操作的函数,有时却没有,你可以使用Observable.of()
进行非异步返回:
getTreeViewChildNodes(currNode: any, nodeType: string, nodeTypeEnum: number = 0, nested: boolean = true): Observable<any> {
if (doSynchronousWork) {
// more code..
let someTree = getStuff();
return Observable.of(someTree);
}
if (doAsynchronousWork) {
return this.siteConfigService.getHostAccessPoints().map(data => {
// more code..
let someTree = getStuff();
return someTree;
});
}
}