Angular:检查Observable/BehaviorSubject是否有相关变化
Angular: check if Observable / BehaviorSubject has relevant changes
我有一个在会员服务中观察到的用户对象。
我只想在用户对象发生相关变化时更新我的服务。
为了了解我的用户对象是否有相关变化,我将我的本地用户对象与观察到的用户对象进行了比较。然后总是分配新对象。
然而,这不起作用。
export class MemberService {
private subscription?: Subscription;
user?: User;
constructor(public auth: AuthService) {
this.subscription = this.auth.user$.subscribe((user) => {
const updateServices = this.hasUserRelevantChanges(user)
// apparently this line always fires before the functioncall above?!
this.user = user;
if (updateServices) {
this.updateMyServices();
}
});
}
ngOnDestroy() {
this.subscription?.unsubscribe();
}
hasUserRelevantChanges(user: User | undefined): boolean {
return user?.subscription !== this.user?.subscription ||
user?.username !== this.user?.username ||
user?.isBanned !== this.user?.isBanned;
}
updateMyServices(): void {
// Updating my services!!!
}
}
export class AuthService {
public readonly user$: Observable<User| undefined> = this.user.asObservable();
user: BehaviorSubject<User| undefined> = new BehaviorSubject<User| undefined>(undefined);
constructor(private httpHandler: HttpHandlerService) { ... }
handleUser(): void {
this.httpHandler.login().subscribe(
(user: User) => this.user.next(user));
}
updateUserData(newUser: User): void {
this.user.next(Object.assign(this.user.value, newUser));
}
}
为什么我的函数 hasUserRelevantChanges()
总是比较相同的新对象?本地 this.user
始终保存此检查中已经存在的新值,即使赋值 this.user = user
之后出现?
那么我如何了解我的新 user
对象与 old/previous 用户对象相比是否更改了相关值?
“为什么我的函数 hasUserRelevantChanges()
总是比较相同的新对象?”
那是因为您总是将新值分配给 this.user
变量。理想情况下,如果不同,您需要使用新的 user
仅 更新它。换句话说,它必须移动到 if
块内。
this.subscription = this.auth.user$.subscribe((user) => {
const updateServices = this.hasUserRelevantChanges(user)
if (updateServices) {
this.user = user;
this.updateMyServices();
}
});
更新:pairwise
+ filter
在您的场景中,您最好使用 RxJS pairwise
+ filter
运算符来检查条件。
this.subscription = this.auth.user$.pipe(
pairwise(),
filter(([user1, user2]) => (
user1?.subscription !== user2?.subscription ||
user1?.username !== user2?.username ||
user1?.isBanned !== user2?.isBanned;
))
).subscribe(([user1, user2]) => { // <-- Update 2: ignore `user1`
this.updateMyServices(user2);
);
如果您实际上是将对象的所有属性与其之前的值进行比较,则可以将整个 pairwise
+ filter
替换为 distinctUntilChanged
运算符。
使用 RxJs
操作符。您不需要将用户存储在代码中的某个位置,但您可以使用 pairwise
和 filter
pipe
它。所以它会是这样的:
this.auth.user$.pipe(
pairwise(),
filter(users => userChanged(users[0], users[1]))
... // other operators to handle change - tap, map etc
)
如果将逻辑移至适当的运算符,将会更加清晰。
编辑:Pairwise
returns 两个值:以前的和当前的,filter
- 正如名称所说过滤事件并仅在传递回调时发出下一个 returns true
Edit2:您应该实施 userChanged
或调整您的 hasUserRelevantChanges
,现在您需要传递 2 个参数。
Edit3:为什么您的代码不起作用?因为 Object.assign
不会创建新的对象引用,而是会更改原始对象 - 所以实际上,您每次都在检查同一个对象。
更新:传播运算符:
updateUserData(newUser: User): void {
this.user.next({...this.user.value, ...newUser});
}
我有一个在会员服务中观察到的用户对象。
我只想在用户对象发生相关变化时更新我的服务。
为了了解我的用户对象是否有相关变化,我将我的本地用户对象与观察到的用户对象进行了比较。然后总是分配新对象。
然而,这不起作用。
export class MemberService {
private subscription?: Subscription;
user?: User;
constructor(public auth: AuthService) {
this.subscription = this.auth.user$.subscribe((user) => {
const updateServices = this.hasUserRelevantChanges(user)
// apparently this line always fires before the functioncall above?!
this.user = user;
if (updateServices) {
this.updateMyServices();
}
});
}
ngOnDestroy() {
this.subscription?.unsubscribe();
}
hasUserRelevantChanges(user: User | undefined): boolean {
return user?.subscription !== this.user?.subscription ||
user?.username !== this.user?.username ||
user?.isBanned !== this.user?.isBanned;
}
updateMyServices(): void {
// Updating my services!!!
}
}
export class AuthService {
public readonly user$: Observable<User| undefined> = this.user.asObservable();
user: BehaviorSubject<User| undefined> = new BehaviorSubject<User| undefined>(undefined);
constructor(private httpHandler: HttpHandlerService) { ... }
handleUser(): void {
this.httpHandler.login().subscribe(
(user: User) => this.user.next(user));
}
updateUserData(newUser: User): void {
this.user.next(Object.assign(this.user.value, newUser));
}
}
为什么我的函数 hasUserRelevantChanges()
总是比较相同的新对象?本地 this.user
始终保存此检查中已经存在的新值,即使赋值 this.user = user
之后出现?
那么我如何了解我的新 user
对象与 old/previous 用户对象相比是否更改了相关值?
“为什么我的函数 hasUserRelevantChanges()
总是比较相同的新对象?”
那是因为您总是将新值分配给 this.user
变量。理想情况下,如果不同,您需要使用新的 user
仅 更新它。换句话说,它必须移动到 if
块内。
this.subscription = this.auth.user$.subscribe((user) => {
const updateServices = this.hasUserRelevantChanges(user)
if (updateServices) {
this.user = user;
this.updateMyServices();
}
});
更新:pairwise
+ filter
在您的场景中,您最好使用 RxJS pairwise
+ filter
运算符来检查条件。
this.subscription = this.auth.user$.pipe(
pairwise(),
filter(([user1, user2]) => (
user1?.subscription !== user2?.subscription ||
user1?.username !== user2?.username ||
user1?.isBanned !== user2?.isBanned;
))
).subscribe(([user1, user2]) => { // <-- Update 2: ignore `user1`
this.updateMyServices(user2);
);
如果您实际上是将对象的所有属性与其之前的值进行比较,则可以将整个 pairwise
+ filter
替换为 distinctUntilChanged
运算符。
使用 RxJs
操作符。您不需要将用户存储在代码中的某个位置,但您可以使用 pairwise
和 filter
pipe
它。所以它会是这样的:
this.auth.user$.pipe(
pairwise(),
filter(users => userChanged(users[0], users[1]))
... // other operators to handle change - tap, map etc
)
如果将逻辑移至适当的运算符,将会更加清晰。
编辑:Pairwise
returns 两个值:以前的和当前的,filter
- 正如名称所说过滤事件并仅在传递回调时发出下一个 returns true
Edit2:您应该实施 userChanged
或调整您的 hasUserRelevantChanges
,现在您需要传递 2 个参数。
Edit3:为什么您的代码不起作用?因为 Object.assign
不会创建新的对象引用,而是会更改原始对象 - 所以实际上,您每次都在检查同一个对象。
更新:传播运算符:
updateUserData(newUser: User): void {
this.user.next({...this.user.value, ...newUser});
}