使用主题值时可观察与订购

时间:2019-05-19 16:48:56

标签: angular rxjs

我对Angular还是很陌生,据我所知Subject是用于多播的标准类。尝试该类时,我发现有两种(可能甚至更多)途径来处理其值的变化。

  1. 直接在组件内使用Observable类型的对象

    通过这种方法,在组件内声明了Observable,如下所示:

    foo$ : Observable<boolean>;
    

    ,然后使用以下方法在html文件中使用:

    <p *ngIf="(foo$ | async) as foo">Bar!</p>
    
  2. 第二种方法是在组件内有一个Subscription类型的对象,该对象分配给某些成员变量:

    s: Subscription;
    foo: boolean;
    

    其中的订阅初始化如下:

    constructor(private fbs: FooBarService) {
        this.s = fbs.fooObservable.subscribe(v => this.foo = v);
        //  this.s.unsubscribe() is called within ngOnDestroy()
    }
    

    然后html将使用如下代码:

    <p *ngIf="foo">Bar!</p>
    

除了个人喜好之外,还有其他理由更喜欢其中一种方法吗?

1 个答案:

答案 0 :(得分:3)

  

除了个人喜好之外,还有其他理由更喜欢其中一种方法吗?

这些问题不在本文的讨论范围之内,但是对于社区来说,给出一个普遍的答案是有价值的。两者之间有足够的区别,应该加以讨论。

一种方法称为反应组件,另一种称为有状态组件

反应成分

该视图使用async管道处理来自可观察对象的数据表示。如果组件仅使用可观察对象和async管道进行演示,则该组件为无状态并通过视图自动对更改做出反应。这有助于为模板营造干燥的感觉。

这种方法具有以下优点。

  • 不太可能出现“检查后表达式已更改”错误。
  • 更容易通过可观察对象来表示服务或存储的外部状态。
  • 更容易使用OnPush更改通知。
  • 通过设计这种方法,可以创建响应速度更快的组件,从而使开发人员的工作量大大减少。

此方法具有以下缺点。

  • 开发人员在不了解反应式编程时可能会写data.subscribe(value => this.value = value)
  • 在没有太多解释的情况下,如果合并,切换或合并多个可观察对象,可能很难理解源代码。
  • 介绍内存泄漏和订阅丢失的风险。
  • 开发人员有时会在不了解所有副作用的地方使用运算符。以mergeMap()代替switchMap()为例。
  • 您必须跟踪可观测对象的生命周期。
  • IDE编辑器很难自动完成类型。例如; <ng-container *ngIf="data$ | async as data">将创建一个视图变量 data ,该变量在大多数IDE中都是未知类型。
  • 陡峭的学习曲线。 RXJS不容易掌握。
  • 使用debugger;进行调试很困难,因为该组件没有要调试的状态。
  • 很难进行单元测试。没有组件状态可以断言它是正确的。

状态组件

当组件具有视图模板中使用的属性时,该组件为“有状态” 。必须更改组件的内部状态才能表示视图中的更改,这是Angular中组件的默认类型。

这种方法具有以下优点。

  • 开发,维护和阅读源代码更加容易。
  • @Input()绑定首先是有状态的。
  • IDE具有更好的组件属性自动完成功能。
  • 学习曲线更轻松。无需学习第三方库。
  • 在浏览器中使用debugger;更容易,因为您可以看到组件的当前状态
  • 单元测试更容易。

此方法具有以下缺点。

  • 使用服务的外部状态时,最有可能出现“检查后表达式已更改”错误。
  • 当您混入可观察对象时,源代码会因subscribe()调用而变得混乱。
  • 您必须手动将反应流转换为组件状态,并编写类似data.subscribe(value => this.data = value)的代码。
  • 使用外部可观察物时,变化检测成为一个挑战。
  • 需要更多的代码行来创建可响应外部事件和可观察对象的响应组件。

结论

在决定使用两种方法中的哪一种时。我建议从有状态组件开始,但要提高您对 active 组件的技能。

根据我的经验,反应性组件是必经之路,因为它们是可观察流的目的地。这些组件将可观察到的东西聚集在一起,以创建该数据的响应视图,并且它们对这些流中的更改自动做出反应。同时,将数据合并为目的地是Angular中的一种架构设计。因此,这是一个更广泛的讨论和主题,但请继续学习,您将会到达那里。