【问题标题】:RxJS observable of objects propertyRxJS 可观察对象属性
【发布时间】:2018-03-22 18:14:48
【问题描述】:

我想用 RxJS 观察一个属性的变化。

interface Test {
  required: boolean;
  toObserve: boolean;
}

class TestClass {
  @Input() subject: Subject<Test>;

  registerHandlers() {
    this.subject.filter(element => element.required).subscribe(next =>
      // Observe a property of every element that was registered
      Observable.of(next.toObserve).subscribe(val => {
        if (val) {
          // DO SOMETHING
        } else {
          // DO SOMETHING ELSE
        }
      })
    );
  }
}

我得到了一个主题,新创建的对象被推入其中。有几个组件订阅了这些,并且应该对不同的属性变化做出反应。

在上面的示例中,如果设置了toObserve,我希望组件执行一些操作。这目前只工作一次 - 根据元素在subject.next(element) 注册时的值,执行正确的路径。

但是,一旦我更改了 element.toObserve 的值,什么都没有发生,订阅似乎也没有任何效果了。

【问题讨论】:

  • 您只是将一个对象推送到主题,然后您正在更改同一个对象?
  • 我将几个对象推送到订阅,但我想听听每个对象的变化。

标签: angular typescript rxjs


【解决方案1】:

不建议订阅订阅。我宁愿为您的主题创建一个运营商链并订阅它:

如果您想根据流中的特定属性在组件中执行一些副作用,可以使用 do 运算符:

interface Test {
  required: boolean;
  toObserve: boolean;
}

class TestClass implements OnInit {
  @Input() subject: Subject<Test>;

  ngOnInit() {
    this.registerHandlers().subscribe();
  }

  registerHandlers() {
    return this.subject
     .filter(element => element.required)
     .do(next => {
        if (next.toObserve) {
          // DO SOMETHING
        } else {
          // DO SOMETHING ELSE
        }
     });    
  }
}

【讨论】:

  • 那我也需要订阅这个吗?我想我仍然想念一些东西来完全理解这个订阅是如何工作的。 do 中的这个 sn-p 会不会每次都对属性的变化做出反应,而不会再次将对象推向主题?
  • 这里,你的主体是发射器。这意味着每次更改值时,都必须调用this.subject.next(myNewValue) 来执行 registerHandlers() 中的代码。您还必须订阅该函数,否则如果没有接收者,则执行此代码毫无意义。但是您总是必须手动将数据推送给主题,它不会自动完成。
  • 嗯,我明白了,所以每次某些组件更改任何内容时,我都必须将孔对象再次推送到所有其他组件以便对其做出反应。那么我需要重新考虑我的逻辑......在我再次查看我的漏洞代码之前还有一个问题:不会有新的对象引用或克隆操作?所以当我再次推送它并要求相等时(例如从数据表中删除它)对象将与我推送的第一个实例相同(只是其他道具值)?
  • 即使你改变了你在你的主题中推送的对象的属性,你并没有改变对象引用,所以它应该是一样的(虽然我不确定,最好快速测试)。我建议将您的主题和功能放在服务中,以便需要数据的每个组件都可以订阅它。不要忘记在组件的 ngDestroy 中取消订阅以防止数据泄漏。
  • 对此的小更新:我不想要do,而是直接订阅do 丢弃后续订阅的副作用。让它或多或少地按照我的意愿工作。
【解决方案2】:

抱歉,我认为您还没有完全了解如何正确完成订阅。

你有你的主题

@Input() subject: Subject<Test>;

并且您希望在主题更改时触发操作。然后将此订阅放入您的 ngOnInit() 方法中:

this.subject.subscribe(value => {
   // and here goes your evaluation
   if(value.toObserve) {
      // do something
   } else {
      // do something else
   }
});

你可以走得更远,做这样的事情

this.subject.subscribe(value => {
   // and here goes your evaluation
   if(value.toObserve) {
      // do something
   } else {
      // do something else
   }

   if(value.required) {
      // do something
   } else {
      // do something else
   }
});

【讨论】:

  • 将订阅放在构造函数中可能很危险。看起来在执行构造函数时属性主题可能未定义
  • 这是否意味着在嵌套对象中,每次整个对象中的任何内容发生变化时,这种方法都必须检查 if(value.toObserver) ?如果是这种情况,这种方法很容易,但很快就会变得性能不佳。例如,如果 if 子句包含更复杂的函数,或者对象更大一些,组件会在悬停时更改对象。
  • 你说得对。当然,必须确保性能不会降低太多。但这就是订阅基本上必须完成的方式。如何优化这些主题的更新过程取决于您。 --- 如果你通过将 Angular 提供的所有生命周期钩子(OnInit、AfterViewInit、AfterContentInit 等)放在一个仅包含一个输入字段的单个组件中来运行一个小测试,并让它们都使用 console.log 触发输出( ) 每当它们被调用时,您会惊讶或震惊 Angular 传递/触发所有它们的频率。
猜你喜欢
  • 1970-01-01
  • 2016-06-18
  • 2022-11-25
  • 1970-01-01
  • 2020-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-30
相关资源
最近更新 更多