2017-03-16 114 views
1

大家早上好。我是Angular2的新手,在我正在開發的一個項目中,我必須提出一些HTTP請求才能從REST後端檢索數據。Angular2 + RxJS嵌套的HTTP調用

從後端我得到一個模塊列表。每個模塊都有一個或多個操作。代表兩個實體的打字稿類以下

export class Module { 

    public name: string; 
    public htmlPath: string; 
    public actions: ModuleAction[]; 

    constructor(data: IModule){ 
     this.name = data.name; 
     this.actions = [];  
     this.htmlPath = data.htmlPath; 
    } 

    addAction(action: ModuleAction): void { 
     this.actions.push(action); 
    } 
} 

export class ModuleAction { 
    private name: string; 

    constructor(data: IModuleAction){ 
     this.name = data.actionName; 
    } 
} 

的支持暴露了一個調用來檢索模塊列表沒有相關的動作和第二端點來檢索一個給定模塊的操作列表。爲了初始化我的角度接口,我必須發出第一個HTTP請求來獲取模塊列表。一旦獲得模塊,我必須爲每個模塊提出第二個請求來檢索操作並更新模塊實例。

昨天我試圖用RxJS來獲取數據。唯一的工作解決,我發現已經下

getModules(type?: string) : Observable<Module[]> { 
    let url = ... 
    console.log("getting modules"); 
    return this.http.get(url) 
     .map(res => { 
      let body = res.json(); 
      let modules = body.map(jsModule => { 
      let m = new Module(jsModule); 
      let url = HttpHandlerService.URL_INFO + '/' + m.htmlPath; 

      console.log("getting actions for module " + m.name); 
      this.http.get(url) 
       .map(response => { 
        let body = response.json(); 
        return body.actions.map(function(a : IModuleAction){ 
        return new ModuleAction(a); 
        }); 
       }) 
       .subscribe(actions => { 
        for(let a of actions) 
        m.addAction(a); 
       }); 
      return m; 
      }); 
      return modules; 
     }) 
     .catch(this.handleError); 
} 

我敢肯定的是我錯用RxJS操作,並且必須有不同的解決方案,以獲得更多的「RxJS符合」相同的結果辦法。

如何使用RxJS操作符來獲得相同的結果? 非常感謝您的幫助。

+0

什麼錯誤得到? –

+0

@VinayPandya我沒有得到任何錯誤。我只是想知道是否有更好的方法使用RxJS操作符來執行相同的操作 – hara

+0

查看http://stackoverflow.com/documentation/rxjs/8247/common-recipes/27973/sending-multiple-parallel-http -requests#t = 20170316111633998635或http://stackoverflow.com/documentation/rxjs/8247/common-recipes/28035/sending-multiple-sequential-http-requests#t=201703161116455216797 – martin

回答

0

嘗試做一些分離和使用switchMap:

getModules(type?: string) : Observable<Module[]> { 
    let url = ... 
    console.log("getting modules"); 
    return this.http.get(url) 
     .switchMap(res => { 
      let body = res.json(); 
      return getJsModules(body); 
     }) 
     .catch(this.handleError); 
} 



getJsModules(body){ 
    return body.switchMap(jsModule => { 
      let m = new Module(jsModule); 
      let url = HttpHandlerService.URL_INFO + '/' + m.htmlPath; 

      console.log("getting actions for module " + m.name); 

      return getModuleActions.map(actions => { 
        for(let a of actions) 
         m.addAction(a); 
        }); 
      }); 
} 


getModuleActions(url){ 
    return this.http.get() 
     .switchMap(response => { 
      let body = response.json(); 
      return body.actions.map(function(a : IModuleAction){ 
       return new ModuleAction(a); 
      }); 
     }) 
} 
0

我會用flatMap和forkJoin:

this.http.get(url) 
    .flatMap(t=> { 
     let urls = getUrls(t.json()) 
      .map(url=> this.http.get(url).map(t=>getActions(t.json())); 
     return Observable.forkJoin(urls).map(x=> [].concat(...x));   
    } 
//.subscribe => [ModuleAction, ModuleAction, ModuleAction,...] 

其中

getUrls(body:[]): string[] { 
    return body.map(jsModule => { 
     let m = new Module(jsModule); 
     let url = HttpHandlerService.URL_INFO + '/' + m.htmlPath; 
     return url; 
    }; 
} 

getActions(body:any): ModuleAction[] { 
    return body.actions.map((a:IModuleAction) => new ModuleAction(a)); 
}