Как 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 ответ
На самом деле я допустил ошибку и неправильное толкование. Сигналы не были причиной такого поведения, и на самом деле оно было таким же, как и без сигналов.
Когда подписчик меняет значение объекта воспроизведения, кажется, что значение объекта также изменяется без выдачи.
Думаю, если я не хочу такого поведения, мне следует клонировать объект.