angular - 如何在不丢失活跃订阅者的情况下更新 Observable?
问题描述
我目前在尝试使用publishReplay
and更新缓存值时遇到了一些麻烦refCount
。
首先,有问题的方法
getCurrentUser(): Observable<User> {
if (!this.jwtService.getToken() || this.jwtService.getAnonymousToken()) { return of(null); }
if (!this.currentUser$) {
console.warn('user.service.getcurrentuser -> load and CACHE it once');
this.currentUser$ = this.userService.loadCurrentUser().pipe(
// https://medium.com/angular-in-depth/fastest-way-to-cache-for-lazy-developers-angular-with-rxjs-444a198ed6a6
publishReplay(1),
refCount()
);
}
console.log('user.service.getcurrentuser -> get from CACHE');
return this.currentUser$;
}
this.currentUser$
是一个 Observable 类型User
。
该方法本身按预期工作,该方法的第一次调用从服务器加载当前用户。随后的调用将获取缓存的条目。但是,我现在要做的是删除缓存的值并从服务器重新加载用户(即在前端编辑了某些内容并且用户数据需要重新加载)。
我做到了
removeCachedUser(): void {
this.currentUser$ = null;
}
通过这样做,方法中的if
条件getCurrentUser
被触发,用户从服务器重新加载。到目前为止,一切都很好。
我面临的问题是getCurrentUser
在缓存重置之前订阅的方法没有收到任何更新,即
ngOnInit() {
this.currentUser$ = this.authService.getCurrentUser();
}
我怀疑这是因为我覆盖了this.currentUser$
Observable。
this.currentUser$ = this.userService.loadCurrentUser()
这篇文章或多或少地证实了我的理论。
我对吗?如果是这样,处理这个问题的正确方法是什么?不幸的是,我没有反应式后端,所以我必须手动触发重新加载。提前致谢!
解决方案
您必须创建一个可以多次发出的 Observable 才能向活动订阅者发送新值。在您当前的设置this.currentUser$
完成时this.userService.loadCurrentUser()
完成。我怀疑loadCurrentUser
是一个发出一次并完成的http请求。所以this.currentUser$
不能多次发射。
要创建可以多次发出的 Observable,请使用 aSubject
作为源并映射到您的 http 请求。要让用户在第一次订阅currentUser$
之前reloadUser()
被调用,这Subject
应该是一个BehaviorSubject
.
private _reloadUser = new BehaviorSubject<void>(0 as void);
currentUser$ = this._reloadUser.pipe(
switchMap(() => {
if (!this.jwtService.getToken() || this.jwtService.getAnonymousToken()) {
return of(null);
}
console.warn('user.service.getcurrentuser -> load and CACHE it');
return this.userService.loadCurrentUser();
}),
shareReplay(1),
tap(user => console.log('user from CACHE:', user))
)
reloadUser() {
this._reloadUser.next();
}
switchMap
调用 to将reloadUser()
取消任何正在进行的加载请求并发送新的加载请求。如果当前正在加载用户,您也可以使用if 调用不应该重新加载用户来exhaustMap
代替。switchMap
reloadUser()
shareReplay(1)
比publishReplay(1), refCount()
在这种情况下更适合,因为默认情况下它没有该refCount
功能。如果没有任何订阅者,publishReplay(1), refCount()
新订阅者将触发加载请求。在这种情况下,将改为从“缓存”返回当前用户。currentUser$
shareReplay(1)
推荐阅读
- javascript - 在Javascript中添加一个href标签
- python - GNU Radio:根据输入信号强度改变输出功率
- java - 获取 2 个列表之间的所有相同内容
- feathersjs - feathersjs - 如何远程检索可用服务
- php - index.php 重定向到哪个路由?
- php - PHP - MySQLi 准备好的语句:未知的“max”函数(错误 1630)
- matlab - 如何在txt文件中的特定单词或字符串之后获取数字数组并获取此行号
- conv-neural-network - PyTorch 中的全卷积神经网络会最大程度地减少损失,但所有预测都相同?
- convex-optimization - L2 Norm 和 sum_of_square() 之间的 cvxpy 库有什么不同吗?
- angular - Angular + express + nodemailer 不工作