Как Angular Signals влияют на Observables RXJS и что происходит с обнаружением изменений в этом случае

Я пытаюсь переключиться на сигналы в своем приложении 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();
  }
}

Затем у меня есть компонент A, который подписывается на пользователя:

      export class aComponent {

 currentUser: User;

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

И у меня есть компонент aChild, который является дочерним элементом компонента A, а также подписывается на пользователя и также может манипулировать пользователем. Имеет возможность изменить/удалить адрес Пользователя. Прежде чем использовать сигналы, я бы мгновенно обновил адрес моего объекта currentUser компонента, чтобы пользователь мог мгновенно увидеть результат, и я бы вызвал «reloadUser()» из службы, чтобы глобальный пользователь был обновлен, а «Компонент " имеет правильное значение (возможно, это не лучшее решение, поскольку оно ведет к другому 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();
  }
 }
}

После того, как я реализовал компонент aChild с сигналами, которые я обнаружил, мне больше не нужно вызывать «reloadUser()» и что значение объекта «currentUser» компонента A уже имеет обновленный адрес.

      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));
  }
 }
}

Я не знаю, является ли это ожидаемым поведением, это анти-паттерн, или оно совершенно неожиданное, или такое поведение совершенно нормально. Однако я не до конца понимаю, почему это происходит и как это работает, потому что в «Компоненте A» подписка на getUser() не запускается после изменения сигнала в дочернем компоненте. Значение меняет то, что кажется для каждой ссылки. Меня также беспокоит, как будет работать обнаружение изменений в этом случае, когда Zone.js больше не существует и приложение работает исключительно с Signals. Поскольку в «Компоненте A» currentUser не является сигналом, но его адрес все равно меняется (с помощью какой-то магии), как это изменение обнаруживается в моем html-коде?

1 ответ

На самом деле я допустил ошибку и неправильное толкование. Сигналы не были причиной такого поведения, и на самом деле оно было таким же, как и без сигналов.

Когда подписчик меняет значение объекта воспроизведения, кажется, что значение объекта также изменяется без выдачи.

Думаю, если я не хочу такого поведения, мне следует клонировать объект.

Другие вопросы по тегам