【问题标题】:Angular6 : Wait nested call API before display an array angular materialAngular6:在显示数组角度材料之前等待嵌套调用 API
【发布时间】:2019-01-15 08:53:11
【问题描述】:

当前行为

  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:

【问题讨论】:

  • 如果您遇到问题,我们可以提供帮助。如果您根本不知道如何做您想做的事,我建议您阅读文档:angular.io
  • 我在 angular doc =s 中找不到类似的东西
  • 在显示数据之前等待 HTTP 调用完成?那么你没有正确阅读文档:conditonal display with ngIf
  • 老兄请阅读我的帖子...我不等待一个简单的 HTTP 调用...我需要了解如何在嵌套请求中执行某些操作,第二个依赖项在第一个请求中接收... Angular-tour-of-heroes 教程没有解释。
  • 我读过你的帖子,你的英语很糟糕,我不明白你面临的问题。鉴于您验证的响应,这在 RxJS 文档中。无论如何,你已经解决了你的问题,太好了,祝你的项目好运!

标签: angular rxjs angular6


【解决方案1】:

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

使用 RxJs 的正确方法更像是这样

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})

基本上这段代码的作用是

  • 调用您的第一个服务以获取用户数组
  • 将数组转换为用户的 Observable(即 用户)与map 和from
  • 为每个用户调用第二个服务并设置每个用户的位置 具有返回结果的用户 - 这是通过 mergeMap 和 以下管道tap
  • 最终用toArray 转换数组中的用户流
  • 现在你可以订阅了,你得到的是一个用户数组 他们的位置,你可以做任何你需要做的事情

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

我建议您花一些时间研究 RxJs 并了解它的机制。即使不是在 Angular 的上下文中,this is an article 也解释了我之前谈到的运算符是如何工作的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多