如何让 forEach 等待订阅完成?

How to make forEach wait for subscribe to finish?

我正在使用 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来延迟,还是不行。

Array.forEach 仅适用于同步函数。将其更改为使用确实有效的 for...of 语法。接下来你 resolve Promise 在调用 getLocation 之前完成并且 subscribe 中的代码有 运行。更改代码以在 getLocation.subscribe.

中调用 resolve
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 而不是局部变量。鉴于它在每次迭代中都会被覆盖,这对我来说似乎有点无用。