簡體   English   中英

Angular 5:從函數返回一個Observable

[英]Angular 5: Returning an Observable from a function

在過去,我會定義一個新的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僅在我調用服務的地方TypeError: Cannot read property 'subscribe' of undefined而服務又依次調用http.get():

 this.configService.getTreeViewChildNodes(this.selectedTreeViewItem, type, nodetype, true).subscribe(data => {
        this.rebuildNetworkTree(data);
    });

大概,您應該使用Subject,就像這樣:

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訂閱者都會收到該值。

對於第二個示例要返回的內容,我無法提供足夠的詳細信息,但是第一個示例的更好方法是沒有new Observable(...)東西。 最好只使用map運算符來轉換數據。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM