【发布时间】:2020-11-06 03:03:11
【问题描述】:
我有一个用户服务,它允许登录、注销并维护有关当前登录用户的数据:
user$ = this.http.get<User>('/api/user')
.pipe(
shareReplay(1),
);
我正在使用shareReplay(1),因为我不希望多次调用 Web 服务。
在其中一个组件上,我有这个(为简单起见),但如果用户登录,我还有其他几件事要做:
<div *ngIf="isUserLoggedIn$ | async">Logout</div>
isUserLoggedIn$ = this.userService.user$
.pipe(
map(user => user != null),
catchError(error => of(false)),
);
但是,isLoggedIn$ 在用户登录或注销后不会更改。当我刷新页面时它确实会改变。
这是我的注销代码:
logout() {
console.log('logging out');
this.cookieService.deleteAll('/');
this.user$ = null;
console.log('redirecting');
this.router.navigateByUrl('/login');
}
我知道如果我将变量分配给 null,内部 observable 不会重置。
所以,对于注销,我从这个答案中得到了线索:https://stackoverflow.com/a/56031703 关于刷新shareReplay()。但是,模板中使用的 user$ 会导致我的应用程序在我尝试注销时立即陷入困境。
在我的一次尝试中,我尝试了BehaviorSubject:
user$ = new BehaviorSubject<User>(null);
constructor() {
this.http.get<User>('/api/user')
.pipe(take(1), map((user) => this.user$.next(user))
.subscribe();
}
logout() {
...
this.user$.next(null);
...
}
这会更好一些,除非我刷新页面。 auth-guard (CanActivate) 总是将 user$ 设为 null 并重定向到登录页面。
当我刚开始时,这似乎是一件容易的事,但随着每次更改,我都会陷入更深的困境。有解决办法吗?
【问题讨论】:
-
您从不在构造函数中分配
$user,这可能是您在auth-gaurd中收到错误的原因。那应该是this.user$ = this.http.get<User>..... -
另外,我会让我的服务无状态但是如果你想像在使用
user$的对象中那样跟踪状态shareReplay,我会从消耗组件。创建一个类似getUser的方法并让它返回一个 observable 并将user$设为私有。该方法可以处理分配user$并返回它或返回现有user$值的实现。 -
如果您需要更多帮助,请提供您问题中代码的完整实现,另请参阅minimal reproducible example。
-
@Igor,感谢您的回复。
user$正在构造函数中初始化 -
在行为主题中粘贴数据是当今 Angular 的标准做法。即使你使用一些像 ngrx 这样的状态管理库,你也会在后台将你的数据粘贴到行为主题中。
标签: angular typescript rxjs rxjs6 rxjs-observables