Angular6:在显示数组角度材质之前,请等待嵌套调用API

时间:2018-08-08 07:21:55

标签: angular rxjs angular6

当前行为

  1. 使用我的http服务调用api以获取所有用户
  2. 对于每个用户(循环),使用我的http服务调用api(其他实体)以获取用户的所有位置。
  3. 我需要与他的用户关联位置(按要求返回)。
  4. 显示数组(角材料的mat-tab)
  5. 我的数组为空或每个用户对象中缺少位置...

预期行为

在打印mat-tab之前,我需要使用用户及其位置构建一个数组。

通过说明将问题最小化

在我的组件中:

public userWithLocations          = [];

ngOnInit () {
        this.loadData();    
    }

loadData() {
        let that = this;
        // get all users
        this.httpSrv.getAllUsers()
            .subscribe(allUser => {

                for (let user in allUser) {

                    let currentUser = allUser[user];

                    // get locations by user
                    this.httpSrv.getLocationsByUser(allUser[user]['_id'])
                        .subscribe((locations) => {

                            currentUser.nb_location = locations;

                            that.userWithLocations.push(currentUser);
                    })
                }

                console.log(that.userWithLocations); // => []

                // Here i need my array with for each user an attribute with locations count

                // init MatTableDataSource dataSource only when receive data (NOT BEFORE)!
                this.dataSource = new MatTableDataSource(that.userWithLocations);
                // init paginator
                this.dataSource.paginator = this.paginator;
                // // init sort
                this.dataSource.sort = this.sort;
            });
    }

在我的服务(http)中:

    // Users requests
    getAllUsers(): Observable<any> {
        // return Observable
        return this.http.get(this.apiURL + 'users');
    }

    getLocationsByUser(id): Observable<any> {
        // return Observable
        return this.http.get(this.apiURL + '/locations/' + id)
            .pipe(map(locations => { return this.size(locations)}));
    }

    // Object length
    size(obj) {
        var size = 0, key;
        for (key in obj) {
            if (obj.hasOwnProperty(key)) size++;
        }

        return size;
    };

改变行为的动机/用例是什么?

我是年轻的开发人员,是angular 6的初学者,我尝试学习如何使用rxjs做嵌套调用api。

环境


Angular version: X.Y.Z

> Angular CLI: 6.0.8
> Node: 10.4.0
> OS: darwin x64
> Angular: 6.0.4
> 
> Package                           Version
> -----------------------------------------------------------
> @angular-devkit/architect         0.6.8
> @angular-devkit/build-angular     0.6.8
> @angular-devkit/build-optimizer   0.6.8
> @angular-devkit/core              0.6.8
> @angular-devkit/schematics        0.6.8
> @angular/animations               6.0.5
> @angular/cdk                      6.2.1
> @angular/cli                      6.0.8
> @angular/flex-layout              6.0.0-beta.15
> @angular/material                 6.2.1
> @ngtools/webpack                  6.0.8
> @schematics/angular               0.6.8
> @schematics/update                0.6.8
> rxjs                              6.2.1
> typescript                        2.7.2
> webpack                           4.8.3

Browser:
- [x] Chrome (desktop) Version 68.0.3440.84
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

For Tooling issues:
- Node: 10.4.0
- Platform:  Mac

Others:

1 个答案:

答案 0 :(得分:3)

代码中的一个问题是您在订阅中进行订阅。这是必须避免的事情。明显是滥用RxJ的迹象。

使用RxJ的正确方法更多是这样的

this.httpSrv.getAllUsers()
.pipe(
  map(users => from(users)),
  mergeMap(user => this.httpSrv.getLocationsByUser(user[_id])
                   .pipe(
                      tap(locations => user.nb_location = locations;
                   )
           ),
  toArray()
)
.subscribe(userWithLocations => {// do what you need to do})

这段代码基本上是

  • 致电您的第一个服务以吸引用户
  • 将数组转换为可观察的用户(即 用户)和mapfrom
  • 为每个用户调用第二个服务并设置每个用户的位置 用户返回的结果-使用mergeMap和 以下通过管道tap
  • 最终使用toArray转换数组中的用户流
  • 现在您可以订阅,您所获得的是一系列用户 他们的位置,您可以根据需要进行任何操作

您的原始代码中的问题是,由于http调用的异步特性,当退出for循环时,尚未执行用于获取位置的各种调用。他们将在一段时间后返回结果。同时,您的userWithLocations显然是一个空数组。

我建议您花一些时间研究RxJ,并了解其机制。即使没有在Angular的上下文中,this is an article也会解释我在工作之前谈论过的运算符。