Angular 8 .next 似乎没有按预期工作
Angular 8 .next doesn't seem to work as expected
我正在尝试创建一个服务来验证用户并将令牌存储在 localStorage 中。
我希望其他服务(特别是 auth guard)能够访问当前用户,所以我设置了这样的身份验证服务的构造函数:
currentUserSubject: BehaviorSubject<Token>;
constructor(private http: HttpClient) {
this.currentUserSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('currentUser')));
}
当用户使用 http POST 请求登录时,如果成功调用 currentSubject
上的 next
方法,如下所示:
return this.http.post<Token>(`${environment.identityServerUrl}/connect/token`, params, httpOptions)
.pipe(map(user => {
localStorage.setItem('currentUser', JSON.stringify(user));
console.log(user);
this.currentUserSubject.next(user);
}));
问题是,它似乎不起作用。如果我检查我的 auth guard,它只会将用户视为 null。只有当我刷新时它才会被填充(因为身份验证服务构造函数)。
我的授权守卫看起来像这样:
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { mapTo, take, filter } from 'rxjs/operators';
import { AuthenticationService } from './authentication.service';
@Injectable({ providedIn: 'root' })
export class AuthGuardService implements CanActivate {
constructor(
private router: Router,
private authenticationService: AuthenticationService
) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authenticationService.currentUserSubject.pipe(
filter(user => !!user),
mapTo(true),
take(1)
);
}
}
有谁知道我做错了什么吗?
如果我将 canActivate
方法更改为:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean|UrlTree {
var user = this.authenticationService.currentUserSubject.value;
console.log(user);
if (user) return true;
this.router.navigate(["login"],{ queryParams: { retUrl: route.url} });
return false;
}
它应该可以工作,但它只是控制台日志显示 null
,所以它只停留在登录页面上。
我看到你可以从这篇文章中得到.value
:
https://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0
主题 next()
方法用于将消息发送到可观察对象,然后将消息发送到订阅该可观察对象的 angular 组件。
您只创建了一个主题,但您还没有创建一个您的守卫可以订阅的可观察对象。
currentUserSubject: BehaviorSubject<Token>;
currentUser$ = this.currentUserSubject.asObservable();
constructor(private http: HttpClient) {
this.currentUserSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('currentUser')));
}
按照惯例,可观察对象在末尾有一个 $
符号。现在我们已经创建了一个可接收您主题消息的可观察对象,我们可以在守卫中订阅它。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authenticationService.currentUser$.subscribe(user => {
console.log(user);
});
}
我也不确定你为什么要使用 filter
,使用 map
应该就足够了。
我正在尝试创建一个服务来验证用户并将令牌存储在 localStorage 中。 我希望其他服务(特别是 auth guard)能够访问当前用户,所以我设置了这样的身份验证服务的构造函数:
currentUserSubject: BehaviorSubject<Token>;
constructor(private http: HttpClient) {
this.currentUserSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('currentUser')));
}
当用户使用 http POST 请求登录时,如果成功调用 currentSubject
上的 next
方法,如下所示:
return this.http.post<Token>(`${environment.identityServerUrl}/connect/token`, params, httpOptions)
.pipe(map(user => {
localStorage.setItem('currentUser', JSON.stringify(user));
console.log(user);
this.currentUserSubject.next(user);
}));
问题是,它似乎不起作用。如果我检查我的 auth guard,它只会将用户视为 null。只有当我刷新时它才会被填充(因为身份验证服务构造函数)。
我的授权守卫看起来像这样:
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs';
import { mapTo, take, filter } from 'rxjs/operators';
import { AuthenticationService } from './authentication.service';
@Injectable({ providedIn: 'root' })
export class AuthGuardService implements CanActivate {
constructor(
private router: Router,
private authenticationService: AuthenticationService
) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authenticationService.currentUserSubject.pipe(
filter(user => !!user),
mapTo(true),
take(1)
);
}
}
有谁知道我做错了什么吗?
如果我将 canActivate
方法更改为:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean|UrlTree {
var user = this.authenticationService.currentUserSubject.value;
console.log(user);
if (user) return true;
this.router.navigate(["login"],{ queryParams: { retUrl: route.url} });
return false;
}
它应该可以工作,但它只是控制台日志显示 null
,所以它只停留在登录页面上。
我看到你可以从这篇文章中得到.value
:
https://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0
主题 next()
方法用于将消息发送到可观察对象,然后将消息发送到订阅该可观察对象的 angular 组件。
您只创建了一个主题,但您还没有创建一个您的守卫可以订阅的可观察对象。
currentUserSubject: BehaviorSubject<Token>;
currentUser$ = this.currentUserSubject.asObservable();
constructor(private http: HttpClient) {
this.currentUserSubject = new BehaviorSubject<Token>(JSON.parse(localStorage.getItem('currentUser')));
}
按照惯例,可观察对象在末尾有一个 $
符号。现在我们已经创建了一个可接收您主题消息的可观察对象,我们可以在守卫中订阅它。
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authenticationService.currentUser$.subscribe(user => {
console.log(user);
});
}
我也不确定你为什么要使用 filter
,使用 map
应该就足够了。