问题
I am using an "auth service" to keep all the user authentication functions. When the user is authenticated, I get the user's id and I fetch the relevant record from the database table, but I fail to get the value of the "role" field. The code I am using in the constructor is this:
constructor(
private _firebaseAuth: AngularFireAuth,
private db: AngularFireDatabase,
private router: Router) {
this.user = _firebaseAuth.authState;
this.user.subscribe(
(user) => {
if (user) {
this.userDetails = user;
this.userEmail = this.userDetails.email;
this.uid = this.userDetails.uid;
this.getUserRole(this.uid).subscribe(result => {
this.role = result.role;
console.log('role >>>>>>>>>>>>>', this.role);
});
console.log('uid >>>>>>>>>>>>>', this.uid);
console.log('role >>>>>>>>>>>>>', this.role);
}
else {
this.userDetails = null;
}
}
);
}
getUserRole(userId: string): Observable<any> {
return this.db.list('users', ref => ref.orderByChild('uid').equalTo(this.uid)).valueChanges()
.map(result => result[0]);
}
this.uid
has the correct value, but this.role
is undefined.
I suppose the problem that the call to the database table is asynchronous. How can i get this value?
回答1:
I have added some code to make you understand the callbacks of observable. Have a look at it.
this.currUser.subscribe(
(val) => {
// This is called as success callback
this.role = val[0].role;
// perform task using this.role. You should be writing your code here.
},
(error) => {
// This is called as error callback, It will be executed if any erorrs were thrown from `currUser()`
// log if there are any errors here
},
() => {
// This is called as complete block
// This will be executed after success callback or the error callback.
}
);
UPDATE :
this.user.subscribe(
(user) => {
if (user) {
this.userDetails = user;
this.userEmail = this.userDetails.email;
this.uid = this.userDetails.uid;
this.getUserRole(this.uid).subscribe(result => {
this.role = result.role;
console.log('role >>>>>>>>>>>>>', this.role); // print log 1
});
// log 2 will be executed before log 1 this is due to asynchronous behaviour
console.log('role >>>>>>>>>>>>>', this.role); // print log 2
}
else {
this.userDetails = null;
}
}
);
log 2 will be executed before log 1 this is due to asynchronous behaviour. If you are thinking that your code executes sequentially with line numbers, then you are wrong. getUserRole
is asynchronous method.
You can access this.role
from other components as well using get
or set
. Whatever you have done is appropriate.
What you should be doing is fetch this.role
only if it is not undefined.
In your external component where your are trying to access this.role
, check for undefined
first and then access it.
some-other component .ts
if(this.role != undefined){
let role = this.role
}
DEMO : Check here to see how asynchronous methods work
回答2:
You cannot access the variable outside .subscribe() method, place it within the subscribe
this.currUser.subscribe(val => {
this.role = val[0].role;
console.log(this.role);
});
回答3:
I created the following function in the user service:
getUserRole(userId: string): Observable<any> {
return this.db.list('users', ref => ref.orderByChild('uid').equalTo(userId)).valueChanges()
.map(result => result[0]);
}
then I got the user id in the component:
get uid(): string {
return this.authService.uid;
}
set uid(value: string) {
this.authService.uid = value;
}
and called the function in onNgInit():
ngOnInit() {
if (this.uid != undefined) {
let uid = this.uid;
this.userService.getUserRole(this.uid).subscribe(result => {
this.role = result.role;
});
}
}
Finally I used *ngIf="role == '<role>'
in the html template
来源:https://stackoverflow.com/questions/50610498/get-user-role-from-database-based-on-user-id-in-angular