代码之家  ›  专栏  ›  技术社区  ›  bob.mazzo

角度5:从函数返回可观测值

  •  3
  • bob.mazzo  · 技术社区  · 6 年前

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

    然而,真正的函数有更多的检索逻辑。设置的正确方法是什么 可观察到 根据我的上述测试功能?完全相同的模式,只需将所有代码包装在 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 回复  |  直到 6 年前
        1
  •  4
  •   Daniel W Strimpel Michael Dorgan    6 年前

    关于您的第二个示例试图返回的内容,我无法估计足够的细节,但更好的方法是不使用 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;
            });
        }
    }
    
        2
  •  4
  •   Anna    6 年前

    也许,你应该使用一个主题,某种程度上像这样:

    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 订阅者将收到该值。