Reputation: 549
I have implemented FireDatabaseService
as @Injectable({ providedIn: 'root' })
in my app. It of course works with DI. In this service I need Firebase UID from another service, but this UID is being fetched with subscription. Because of this methods that need UID are called before this UID is available. I have no idea how to get UID before getUserGroup()
is called. Here is my service:
...
@Injectable({ providedIn: 'root' })
export class FireDatabaseService {
uid: string;
constructor(
private readonly db: AngularFireDatabase,
private readonly authService: AuthService
) {
this.authService.authState.subscribe(
(state: firebase.User) => this.uid = state.uid
);
}
getUserGroup(): Observable<string> {
return this.db
.object(`users/${this.uid}`)
.valueChanges()
.pipe(map((userData: any) => userData?.group as string));
...
}
Calling fireDatabaseService.getUserGroup()
goes with uid = ''
. Is there any possibility to fix it? Thanks for help.
Upvotes: 0
Views: 97
Reputation: 14740
I suggest that you do not subscribe at all in your service, but rather define your uid
and userGroup
as observables. The userGroup$
can be defined from the uid$
observable:
@Injectable({ providedIn: 'root' })
export class FireDatabaseService {
uid$ = this.authService.authState.pipe(
map(state => state.uid)
);
userGroup$ = this.uid$.pipe(
switchMap(uid => this.db.object(`users/${uid}`).valueChanges())
map(userData => userData?.group as string)
);
constructor(
private readonly db: AngularFireDatabase,
private readonly authService: AuthService
) { }
}
Observables are lazy, so it is not necessary to wrap them as functions. They don't emit a value until .subscribe()
is called on them.
Upvotes: 0
Reputation: 11474
It is a little unclear to me what your requirements are. The easiest way to accomplish what I think you are asking would be the following:
...
@Injectable({ providedIn: 'root' })
export class FireDatabaseService {
constructor(
private readonly db: AngularFireDatabase,
private readonly authService: AuthService
) {
}
getUserGroup(): Observable<string> {
return this.authService
.authState
.pipe(
switchMap((state: firebase.User) =>
this.db
.object(`users/${state.uid}`)
.valueChanges()
),
map((userData: any) => userData?.group as string)
);
...
}
Everytime getUserGroup
is called, there would be another call to the authService. That might be undesireable, but that could be mitigated through the use of shareReplay(1)
or through another strategy depending on the functionality you are expecting.
Upvotes: 2