Angular 5:从函数返回Observable

时间:2018-04-04 16:00:13

标签: angular observable angular5

在过去,我会定义一个新的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);
    });

2 个答案:

答案 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;
        });
    }
}