2017-03-16 90 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)); 
}