如何让forEach等待订阅完成?

时间:2018-12-24 09:51:16

标签: angular asynchronous promise async-await subscribe

我正在使用Angular 6,我的数据库是Firebase。现在,我尝试根据房间的建筑物显示每个房间的名称。例如:

Building A
Room 1
Room 2
Building B
Room 1
Room 2

但是,每次尝试时,它将首先显示所有建筑物名称,然后才显示房间名称。这就是我现在得到的:

Building A
Building B
Room 1
Room 2

我发现发生这种情况是因为forEach一直跳过subscribe函数。

我尝试使用promiseawait,但是它不起作用。也许是因为我使用错误的方式?我不确定如何正确使用promise

async loadData(){
    this.navigationService.user
        .subscribe( user => {
        console.log(user);
        this.user = user;
        this.navigationService.getBuildings(this.user.orgId)
            .subscribe( building => {
            this.navMasterBuilding = [];
            this.buildings = building;
            this.buildings.forEach( async building2 => {
                this.completeBuildingId = building2.completeBuildingId;
                this.buildingName = building2.buildingName;
                console.log(building2.buildingName);
                await new Promise ((resolve, reject) => { 
                    this.navigationService.getLocation(this.user.orgId, this.completeBuildingId)
                    .subscribe(location => {
                    console.log('room' + location);
                    this.navMasterLocation = [];
                    });
                    resolve();
                });   
            });
        });
    });
}

我已经尝试通过使用setTimeout来延迟它,但是它仍然不起作用。

1 个答案:

答案 0 :(得分:1)

Array.forEach仅适用于同步功能。将其更改为使用有效的for...of语法。在您对resolve的调用已经完成并且Promise中的代码运行之前,您getLocation subscribe旁边。更改代码以在resolve中调用getLocation.subscribe

for(const building2 of buildings) {
    console.log(building2.buildingName);
    await new Promise ((resolve, reject) => { 
        this.navigationService.getLocation(this.user.orgId, this.completeBuildingId)
            .subscribe(location => {
                console.log('room' + location);
                this.navMasterLocation = [];

                resolve();
             });                    
    });   
}

请注意,它可以简化为:

for(const building2 of buildings) {
    console.log(building2.buildingName);
    const location = await this.navigationService.getLocation(this.user.orgId, this.completeBuildingId).toPromise();
    console.log('room' + location);
    this.navMasterLocation = [];             
}

也请注意,我不太确定为什么使用this.completeBuildingId而不是局部变量。鉴于它在每次迭代中都会被覆盖,这对我来说似乎没有用。