Я работаю с Typescript 3.4.5 и Angular 8.
Рассмотрим следующий интерфейс:
// This is an interface which represents a piece of data, which will be partially updated
export interface TextBrick {
kind: 'text';
content: string;
}
export class TestService {
test$ = new BehaviorSubject<TextBrick>({kind: 'text', content: 'initial'});
get test(): TextBrick {
return this.test$.value;
}
set test(v: TextBrick) {
console.log('set', v);
this.test$.next(v);
}
}
Идея состоит в том, чтобы подписаться на test$
BehaviorSubject для просмотра изменения test.content
.
Рассмотрим теперь следующий тест:
test('test', () => {
const instance = new TestService();
// Watch subscription
instance.test$.subscribe((v) => console.log('sub', v));
// 1) Full replace, subscription triggered
instance.test = {kind: 'text', content: 'fullreplace'};
// 2) Partial replace, subscription not triggered
instance.test.content = 'aa';
// But the value of the BehaviorSubject was updated! WTF?!
console.log('end', instance.test);
});
Вывод на консоль следующий:
sub { kind: 'text', content: 'intitial' } // Expected behavior
set { kind: 'text', content: 'fullreplace' } // Expected behavior
sub { kind: 'text', content: 'fullreplace' } // Expected behavior
end { kind: 'text', content: 'aa' } // Sounds really weird!
Очевидно, что существует проблема с «частичным установщиком» (я не знаю, как это назвать), когда я устанавливаю instance.test.content
. Я внимательно прочитал документацию Typescript по сеттерам , но этот вариант использования не упоминается.
Моя первая гипотеза состояла в том, что set test()
не был вызван, что имеет смысл, потому что, когда я добавляю console.log в сеттер, я не вижу "частичного" набора 'aa'
. Но как можно обновить значение темы поведения, не вызывая мой обратный вызов подписки?
Любая помощь или ресурсы будут с благодарностью!