我正在尝试使用Firebase为网站实施持久签名会话。我相信我已经正确地完成了所有操作,除了当用户重新加载页面时,身份验证令牌都可用,但是因为我的函数fetchAuthTokenOnReload()里面有一个诺言(我相信这就是问题所在),仅在浏览器已经呈现我的HTML之后,promise才会被解决。我知道这一点是因为重新加载后,我最初已经退出,但是只要单击诸如导致重新渲染的随机按钮之类的东西,我就会登录。
这很奇怪,因为我没有在Observables中遇到这个问题。我试着四处寻找如何处理承诺以及如何或如何将Promises转换为Observable,但没有成功。在承诺完成后,我还尝试重新路由用户,因为这将导致重新渲染,但没有用。 也很奇怪,因为我的firebase.auth()。signInWithEmailAndPassword(email,password)函数也使用了promise,但是在对int签名后我没有问题。
感谢您的帮助。
auth.service.ts
import { Router } from '@angular/router';
import { Injectable } from '@angular/core';
import * as firebase from 'firebase';
import { Subject } from 'rxjs';
import { ConfirmationModalService } from '../confirmation-modal/confirmation-modal.service';
@Injectable()
export class AuthService {
token: String;
tokenChanged = new Subject<String>();
constructor(
private router: Router,
private confirmationModalService: ConfirmationModalService) { }
signInUser(email: string, password: string) {
firebase
.auth()
.setPersistence(firebase.auth.Auth.Persistence.LOCAL)
.then(() => {
return firebase.auth().signInWithEmailAndPassword(email, password)
.then( // also uses a promise but no problems here
response => {
this.router.navigate(['/']);
firebase.auth().currentUser.getIdToken()
.then(
(token: string) => {
this.token = token;
this.tokenChanged.next(token);
}
);
}
)
.catch(
error => {
console.log(error);
this.confirmationModalService.displayConfirmationModal('invalid username/password', 'failure', 2000);
}
);
}).catch(error => {
console.log(error);
});
}
setAuthToken(token: String) {
console.log('setting auth token');
this.token = token;
this.tokenChanged.next(token);
console.log('set autToken');
}
getAuthToken() {
return this.token;
}
fetchAuthTokenOnReload() {
console.log('fetchAuthTokenOnReload()');
firebase.auth().onAuthStateChanged((user) => {
console.log(this.token);
if (user) {
console.log('already signed in');
console.log('currently authToken = user.getIdToken()');
return user.getIdToken()
.then((token) => {
this.setAuthToken(token);
})
.catch((error) => {
console.log(error);
});
} else {
console.log('not signed in');
console.log(user);
return null;
}
});
}
logout() {
firebase.auth().signOut();
this.token = null;
this.tokenChanged.next(null);
window.location.reload();
}
**app.component.ts**
import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import * as firebase from 'firebase';
import { AuthService } from './auth/auth.service';
import { AngularFireStorage } from 'angularfire2/storage';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
token: String;
isAuthenticated: boolean;
constructor(
private router: Router,
private authService: AuthService,
private afStorage: AngularFireStorage) {
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
(<any>window).ga('set', 'page', event.urlAfterRedirects);
(<any>window).ga('send', 'pageview');
}
});
}
ngOnInit() {
this.authTokenChanged();
this.authService.fetchAuthTokenOnReload();
}
// When the pages has finished loading, this.token has the correct value but the browser uses the previous value, which is undefined at the time
authTokenChanged() {
console.log('inside observable authTokenChaned()');
console.log('authTokenChanged() - before change');
console.log(this.token);
this.authService.tokenChanged.subscribe(
(token) => {
this.token = token;
console.log('authTokenChanged() - after change');
console.log(this.token);
this.router.navigate(['/']);
}
);
}
}
app.component.html
<div *ngIf="token">
<div class="auth-status-bar logged-in">YOU ARE LOGGED IN</div>
</div>
<app-confirmation-modal></app-confirmation-modal>
<div class="container-fluid row">
<div class="col-xs-12" [ngStyle]="{ 'margin-top': token ? '30px' : '0px' }">
<app-header></app-header>
<router-outlet></router-outlet>
<router-outlet name='opportunities'></router-outlet>
<app-footer></app-footer>
</div>
</div>
应该发生的是:重新加载页面后,该div:
<div *ngIf="token">
<div class="auth-status-bar logged-in">YOU ARE LOGGED IN</div>
</div>
应该显示。
答案 0 :(得分:0)
请尝试使用BehaviorSubject而不是使用tokenChanged处的Subject,因为Subject不保留该值,这就是为什么您将其作为null的原因。