【问题标题】:BehaviorSubject partial change does not trigger subscriptionBehaviorSubject 部分更改不会触发订阅
【发布时间】:2019-06-13 06:17:27
【问题描述】:

我正在使用 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 documentation on setters,但是没有提到这个用例。

我的第一个假设是 set test() 没有被调用,这是有道理的,因为当我在 setter 中添加 console.log 时,我看不到 'aa' 的“部分”集。但是如何在不触发我的订阅回调的情况下更新行为主体的值呢?

任何帮助或资源将不胜感激!

【问题讨论】:

    标签: angular typescript rxjs


    【解决方案1】:
    instance.test = {kind: 'text', content: 'fullreplace'};
    

    这一行调用了setter函数

    instance.test.content = 'aa';
    

    此行调用getter函数,然后修改行为主体的内容,你不应该修改行为主体的内容。

    获取值,然后用新对象更新值,我们不会在反应式编程的世界中改变对象。

    const value = instance.test;
    
    instance.test = { ...value, content: 'aa' };
    

    【讨论】:

    • 没错,我刚刚检查过。可悲的是,我认为可以将 BaheviorSubject 更新为instance.text.content。非常感谢您的快速回答!
    • 阅读我关于 Angular 状态管理的文章,它可能会让你思考medium.com/@adrianbrand/…
    猜你喜欢
    • 2018-10-26
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多