Search code examples
javascriptangularfirebaseobservableangularfire2

Wait for Observable to complete in order to submit a form


I have a 'new trip' form, where the user can write the names of the participants and then submit the form to create the trip. On submit, I query a Firebase database with the names, in order to get the IDs of the participants (/users). I then add the IDs to the participantsID field of the trip object and then I push the new trip to Firebase.

The problem is that the Firebase query is async and returns an Observable, therefore my function will proceed to push the object before the Observable has completed, so the participantsID field of the new object is empty.

Is there any method to wait for the observable to complete (in a kind of synchronous way) so that i can manipulate the data and then proceed? All my attempts to fix this have failed so far.

Here's my simple code.

getUserByAttribute(attribute, value) {
  return this.db.list('/users', {
    query: {
      orderByChild: attribute,
      equalTo: value,
      limitToFirst: 1
    }
  });
}

createTrip(trip) {
  for(let name in participantsName.split(',')) {
    getUserByAttribute('username', name)
      .subscribe( user => trip.participantsID.push(user[0].$key) );
  }

  this.db.list('/trips').push(trip);
}

Solution

  • In the end I used part of @Pankaj Parkar's answer to solve the problem. I forkJoin all the Observables returned by mapping the splitted names and I subscribe to that Observable which result contains an array of arrays, where the inner arrays contain a user object.

    getUserByAttribute(attribute, value) {
      return this.db.list('/users', {
        query: {
          orderByChild: attribute,
          equalTo: value,
          limitToFirst: 1
        }
      }).first();
    }
    
    createTrip(trip) {
      Observable.forkJoin(
        trip.participantsName.split(',')
          .map(name => getUserByAttribute('name', name))
        ).subscribe(
          participants => {
            trip.participants = participants.map( p => p[0].$key);
            this.tripService.createTrip(trip);
          }
        );
      }   
    }