本文介绍了Angular2 + RxJS 嵌套 HTTP 调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家早上好.我是 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 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 04:47