简体   繁体   中英

How to make forEach wait for subscribe to finish?

I'm using Angular 6 and my database is Firebase. Now I try to show each of the room's names according to its building. For example:

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

But every time I try, it will show all the building names first, and only then it will show the room's names. This is what I got for now:

Building A
Building B
Room 1
Room 2

I find out this happens because forEach keeps skipping the subscribe function.

I have attempted to use promise and await , but it doesn't work. Maybe because I use it in a wrong way? I'm not so sure how to use promise in a correct way.

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

I have try to delay it by using setTimeout, but it still does't work.

Array.forEach only works with synchronous functions. Change it to using the for...of syntax which does work. Next to that you resolve the Promise before the call to getLocation has finished and the code in subscribe has ran. Change the code to call resolve within the 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();
             });                    
    });   
}

Note that it can be simplified to:

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 = [];             
}

Also do note that I'm not quite sure why you use this.completeBuildingId instead of a local variable. Given that it gets overwritten in each iteration this seems a bit useless to me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM