Search code examples
angularfirebaseangularfireangular2-servicesangular-services

Calling services in the correct order in Angular 4?


Here is my project layout:

enter image description here

Here is the user data service function that returns the user ID:

get uid(): BehaviorSubject<string> {
    const uidSubject: Subject<string> = new Subject<string>();
    this.afAuth.authState.subscribe((data) => {
      uidSubject.next(data.uid);
    });
    return uidSubject;
  }

Then here is the user tasks service that gets the tasks using the ID from the previous service:

  get tasks(): BehaviorSubject<string> {
    const tasksSubject: BehaviorSubject<string> = new BehaviorSubject<string>('no tasks available');
    this.afs.collection(`users/${this.uid}/tasks`).valueChanges().subscribe(tasks=> {
      if (tasks.length !== 0) {
        tasksSubject.next(tasks);
      }
    });
    return tasksSubject;
  }

I then subscribe in the App Component to get the data from the tasks service but the user ID is obviously undefined because the tasks function gets called before the uid function.

So how can make sure that the user data service gets the uid before the tasks service gets called?


Solution

  • I guess a solution is to use Observable's flatMap. Something like this (I rewrote your code, but I couldn't test it)

    get uid(): BehaviorSubject<string> {
      const uidSubject: Subject<string> = new Subject<string>();
      return this.afAuth.authState
    }
    
    get tasks(uid): BehaviorSubject<string> {
      const tasksSubject: BehaviorSubject<string> = new BehaviorSubject<string>('no tasks available');
      return this.afs.collection(`users/${uid}/tasks`).valueChanges()
    }
    
    caller() {
      this.uid().flatMap( data => {
        //pass data as parameter, will be the id
        return this.tasks(data)
      })
      .subscribe( tasks => {
         //do what you need
      })
    }
    

    there is this good thread about this.