Основная проблема в том, что ваш метод login()
является асинхронным, но вы пытаетесь проверить результат, как если бы он был синхронным методом.Кроме того, login()
в настоящее время даже не возвращает ничего void
, поэтому не будет никакого результата для проверки.В любом случае, даже если результат был возвращен как Promise<T>
, вам нужно будет использовать then()
для доступа к результатам / успеху и catch()
для соответствующей обработки ошибок в компоненте.Вы просто не сможете проверить результаты в таком выражении if()
.На базовом уровне, если вы пытаетесь проверить функцию, возвращающую Promise<T>
в операторе if, это всегда будет правдой, независимо от того, будет ли catch()
запущена через миллисекунды.
function login(): Promise<boolean> {
return Promise.resolve(true);
}
if(login()) {} // this is always true regardless of `catch()` is triggered sometime in the future
С angularfire2 вы можете отслеживать состояние аутентификации пользователя в режиме реального времени как Observable<User>
, который можно использовать в таких методах, как canActivate()
.Вот подход, который вы могли бы использовать, который выставляет Observable<User>
в сервисе аутентификации, который можно использовать для проверки статуса входа в систему, получения текущего пользователя или даже в шаблоне для отображения чего-то вроде изображения аватара пользователя с конвейером async
,Есть операторы RxJS, такие как tap
, take
и map
, помогающие избежать ненужной поддержки активных подписок.С этими методами, в основном возвращающими Observable<T>
, вы можете дополнительно направить дополнительные операторы / действия в другие ваши службы или компоненты, чтобы в полной мере использовать RxJS.
Служба аутентификации:
import { AngularFireAuth } from 'angularfire2/auth';
import { User, UserCredential } from '@firebase/auth-types';
@Injectable()
export class AuthService {
user: Observable<User>;
redirectUrl: string;
constructor(private afAuth: AngularFireAuth, private router: Router) {
this.user = this.afAuth.authState;
}
getUser(): Observable<User> {
return this.user.pipe(take(1));
}
isLoggedIn(redirectUrl: string): Observable<boolean> {
return this.user.pipe(
take(1),
map(authState => !!authState),
tap(authenticated => {
if (!authenticated) {
this.redirectUrl = redirectUrl;
this.router.navigate(['/login']);
}
})
);
}
login(username: string, password: string): Promise<UserCredential> {
return this.afAuth.auth.signInWithEmailAndPassword(email, password);
}
logout(): Promise<boolean> {
return this.afAuth.auth.signOut().then(() => this.router.navigate(['/login']));
}
}
Auth Guard:
@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild, CanLoad {
constructor(private authService: AuthService) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
const url: string = state.url;
return this.checkLogin(url);
}
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.canActivate(route, state);
}
canLoad(route: Route): Observable<boolean> {
const url: string = route.path;
return this.checkLogin(url);
}
checkLogin(url: string): Observable<boolean> {
return this.authService.isLoggedIn(url);
}
}
Компонент:
export class LoginComponent implements OnInit {
constructor(private router: Router, public authService: AuthService) { }
ngOnInit() {
this.login(this.email, this.password);
}
login(username: string, password: string): void {
this.authService.login(username, password).then(_ => {
const redirectUrl: string = this.authService.redirectUrl || '/some-default-route';
this.router.navigate([redirectUrl]);
});
}
}
Общая рекомендация, вы захотите воспользоваться лучшими услугами для связи между компонентами.Вы интенсивно используете как DOM-манипуляции с JavaScript, так и jQuery, что противоречит цели Angular и, вероятно, вызовет проблемы, так как элементы будут недоступны, когда вы ожидаете из-за жизненного цикла компонента и рендеринга.Используя сервисы и RxJS, вы можете устанавливать классы CSS с помощью директив ngClass .Ознакомьтесь с документацией по . Родители и дети общаются через службу , чтобы узнать, как компоненты могут взаимодействовать на базовом уровне.Если вам нужен именно Bootstrap, вы должны рассмотреть компоненты / библиотеки Bootstrap на основе Angular, которые подключаются к жизненному циклу компонента Angular и не зависят от jQuery.
Обновление:
На основе предоставленного вами обновленного кода вы все еще пытаетесь проверить успешность асинхронного Promise login()
с помощью оператора if
в своем конструкторе,Это всегда будет вызывать перенаправление, так как login()
возвращает обещание, которое будет иметь истинное значение.Вместо этого попробуйте использовать then()
/ catch()
в возвращенном обещании в вашем LoginComponent
, чтобы ответить на успех / ошибку signInWithEmailAndPassword()
в Firebase:
this.authService.login(this.email, this.password)
.then(result => this.router.navigate(['dashboard']))
.catch(err => {
this.nativeElement = element.nativeElement;
this.sidebarVisible = false;
});
Надеюсь, это поможет!