我开发了具有Firebase后端的Angular 9网站。当用户输入电子邮件和密码进行登录时,我将控制用户的权限并在有许可的情况下将用户定向到另一端。我的问题是第一次单击单击发送未定义错误,但是第二次单击有效。 这是我的代码:
authservice.service.ts文件:
export class AuthService {
userData: any;
user: Observable<User>;
constructor(
public afs: AngularFirestore,
public afAuth: AngularFireAuth,
public router: Router,
private _snackBar: MatSnackBar,
public ngZone: NgZone) {
this.afAuth.onAuthStateChanged((result) => {
if (result) {
this.user = this.afs.collection('user').doc<User>(result.uid).valueChanges();
this.user.subscribe((result) => {
this.userData = result;
});
this.ngZone.run(() => this.router.navigate(['home']));
} else {
localStorage.removeItem('user');
localStorage.removeItem('useremail');
this.ngZone.run(() => this.router.navigate(['sign-in']));
}
});}
async SignIn(email, password) {
await this.afAuth.signInWithEmailAndPassword(email, password)
.then(async (result) => {
localStorage.setItem("useremail", result.user.email);
if ((this.userData.permission & 2) === 2) {
localStorage.setItem('user', JSON.stringify(this.userData));
this.router.navigate(['home']);
}else
this.openSnackBar("You don't have access this area");
}).catch((error) => {
this.openSnackBar(error.message);
});}}
sign-in-component.html:
<form>
<mat-form-field appearance="fill" class="col-12 text-capitalize" color="primary">
<mat-label>email</mat-label>
<input matInput #userEmail required type="email">
</mat-form-field>
<mat-form-field appearance="fill" class="col-12 text-capitalize">
<mat-label>password</mat-label>
<input matInput #userPassword required type="password">
</mat-form-field>
<button class="col-12 text-uppercase" mat-stroked-button color="primary" (click)="authService.SignIn(userEmail.value, userPassword.value)">login</button>
</form>
sign-in-component.ts:
export class SignInComponent implements OnInit {
constructor(public authService: AuthService) { }
ngOnInit(): void {}
}
错误是:this.userData未定义
我不知道我做错了什么。我尝试了differend方法,但没有用。感谢所有帮助。
答案 0 :(得分:1)
如果您需要访问userdata变量,请在订阅中调用获取该变量的方法。
this.user.subscribe((result) => {
this.userData = result;
// you could put calls to other methods that need what you get from result here.
//At this point in time going forward userData is defined.
});
通常,异步动作可能是某些交互作用的结果,这避免了嵌套在侦听器/订户的代码块内的需要,但是如果您以编程方式调用signin(),那么肯定会在设置userData值之前调用它。 / p>
答案 1 :(得分:0)
我用SignIn方法中的this.userData变量解决了我的问题,并将代码更改为以下形式:
async SignIn(email, password) {
await this.afAuth.signInWithEmailAndPassword(email, password)
.then(async (result) => {
this.user = await this.afs.collection('user').doc<User>(result.user.uid).valueChanges();
this.user.subscribe((result) => {
this.userData = result;
if ((this.userData.permission & 2) === 2) {
localStorage.setItem("useremail", result.email);
localStorage.setItem('user', JSON.stringify(this.userData));
this.router.navigate(['home']);
}
else
this.openSnackBar("You don't have access this area");
}).unsubscribe;
}).catch((error) => {
this.openSnackBar(error.message);
});}
当我从Firebase获取用户数据时,查询我的用户权限,如果用户具有权限,则将其指向主页。