角度信号如何影响 RXJS Observables 以及在这种情况下检测会发生什么变化

Til*_*dam 5 rxjs angular2-changedetection angular angular-signals angular16

我正在尝试在 Angular 应用程序中切换到信号,目前在寻找良好实践方面遇到问题,并且我也经历了(至少对我来说)意外的行为。

这是我的代码片段,由一个 userService 和两个组件组成

export class UserService {
  private user$: Observable<User>;
  private refreshUser$ = new BehaviorSubject<void>(undefined);

  constructor(private readonly http: HttpClient) {}

  getUser(): Observable<User> {
    if (!this.user$) {
      this.user$ = this.refreshUser$.pipe(
        switchMap(() => this.http.get<User>('...')),
        shareReplay(1)
      );
    }
    return this.user$;
  }

  reloadUser(): void {
    this.refreshUser$.next();
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我有组件 A 为用户订阅:

export class aComponent {

 currentUser: User;

  constructor(private readonly userService: UserService) {
    this.userService.getUser().subscribe((user) => {
      this.currentUser = user;
    });
 }
}
Run Code Online (Sandbox Code Playgroud)

我有组件 aChild,它是组件 A 的子组件,也订阅用户并且还可以操作用户。它能够更改/删除用户的地址。在使用信号之前,我会立即更新组件的 currentUser 对象的地址,以便用户可以立即看到结果,并且我会从服务调用“reloadUser()”,以便全局用户是最新的,并且“A Component " 具有正确的值(这可能不是最好的解决方案,因为它会导致另一个 http 请求,但这不是这里的主题)。

export class aChildComponent {

 currentUser: User;

  constructor(private readonly userService: UserService) {
    this.userService.getUser().subscribe((user) => {
      this.currentUser = user;
    });
 }


 changeAddress(newAddress: any) {
  this.userService.updateAddress(newAddress).subscribe((updatedAddress) => {
   this.currentUser.address = updatedAddress;
   this.userService.reloadUser();
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

在我使用发现的信号实现 aChild 组件后,我不必再调用“reloadUser()”,并且组件 A 的“currentUser”对象的值已经具有更新的地址。

export class aChildComponent {

  currentUser: WritableSignal<User | undefined> = signal(undefined);

  constructor(private readonly userService: UserService) {
    this.userService.getUser().subscribe((user) => {
      this.currentUser.set(user);
    });
 }


 changeAddress(newAddress: any) {
  this.userService.updateAddress(newAddress).subscribe((updatedAddress) => {
   this.currentUser.mutate((user) => (user.address = updatedAddress));
  }
 }
}
Run Code Online (Sandbox Code Playgroud)

我不知道这是否是预期的行为,而是一种反模式,或者是否完全出乎意料,或者这种行为是否完全正常。但是我不完全理解为什么会发生这种情况以及它是如何工作的,因为在“A Component”中,在子组件中的信号发生变化后, getUser() 上的订阅不会被触发。每个引用的值都会发生变化。我还担心在这种情况下,当不再有 zone.js 并且应用程序仅与 Signals 配合使用时,更改检测将如何工作。由于在“A 组件”中, currentUser 不是信号,但它的地址无论如何都会发生变化(通过一些魔法),如何在我的 html 代码中检测到这种变化?

Til*_*dam 0

我实际上犯了一个错误和误解。信号并不是导致这种行为的原因,实际上与没有信号时的情况相同。

当订阅者更改重播主题的值时,似乎主题上的值也发生了更改,但没有发出。

我想如果我不想要这种行为我应该克隆该对象。