问题描述
大家早上好.我是 Angular2 的新手,在我正在进行的一个项目中,我必须发出一些 HTTP 请求才能从 REST 后端检索数据.
Good morning to everyone. I'm a newbie of Angular2 and in a project I'm working on I have to make some HTTP requests in order to retrieve data from a REST backend.
我必须从后端获取模块列表.每个模块都有一个或多个操作.代表两个实体的打字稿类如下
From the backend I have to get a list of Modules. Each Module has one or more Actions. The typescript classes representing the two entities are the following
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;
}
}
支持公开调用以检索没有相关操作的模块列表,以及用于检索给定模块的操作列表的第二个端点.为了初始化我的 angular 接口,我必须发出第一个 HTTP 请求来获取模块列表.获得模块后,我必须为每个模块发出第二个请求,以检索操作并更新模块实例.
The backed exposes a call to retrieve a list of modules without the relative actions and a second endpoint to retrieve a list of actions for a given module. In order to initialize my angular interface I have to make a first HTTP request to get the modules list. Once obtained the modules I have to make a second request for each one of them to retrieve the actions and update the Module instance.
昨天我尝试使用 RxJS 来获取数据.我发现的唯一可行的解决方案如下
Yesterday I tried to use RxJS to get the data. The only working solution I found has been the following
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"的方式获得相同的结果.
I'm quite sure that I'm wrongly using the RxJS operator and there must be a different solution to obtain the same result in a more "RxJS compliant" way.
如何使用 RxJS 运算符来获得相同的结果?非常感谢您的帮助.
How can I use RxJS operators in order to obtain the same result?Thanks a lot for your help.
推荐答案
可以使用 Observable.flatMap
运算符实现链接相互依赖的 HTTP 请求.请参阅此帖子:Angular 2 - 链接 http 请求
Chaining interdependent HTTP requests can be achieved using the Observable.flatMap
operator. See this post: Angular 2 - Chaining http requests
而且,由于您需要为每个模块检索模块操作,因此请使用 Observable.forkJoin
运算符.请参阅此帖子:并行发送多个 HTTP GET 请求
And, since you need to retrieve module actions for each module, use Observable.forkJoin
operator. See this post: Send multiple HTTP GET requests in parallel
最终的结构类似于:
getModules()
.flatMap(modules => {
this.modules = modules;
let moduleActionsObservables = modules.map(module => {
return this.getModuleActions(module);
});
return Observable.forkJoin(moduleActionsObservables);
})
.map(result) => {
// module actions for each module
console.log(result); // => [[ModuleAction, ModuleAction], [ModuleAction], [ModuleAction, ModuleAction]]
// if you want to assign them to their respective module, then:
this.modules.forEach((module, i) => {
module.actions = result[i];
});
return this.modules;
});
// The result:
this.getModules().subscribe(
modules => {
console.log(modules); // => [{moduleId: '123', actions: [..]}, {moduleId: '124', actions: [..]}]
});
这篇关于Angular2 + RxJS 嵌套 HTTP 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!