RxJS Observable:当对象的特定部分发生变化时发出

时间:2017-07-04 08:25:27

标签: rxjs rxjs5

我有一个包含子对象和数组等的复杂对象。

我可以从这个对象轻松创建一个Subject / BehaviourSubject或Observable,这样我就可以向订阅者“下一步”(发出)新状态。

[例如:let appEnv$ = new Rx.BehaviorSubject<IWebSocketAppEnv>(appEnv);]

但是,每次对象更改时,我都不希望所有订阅者都收到通知。例如,对于我的一个订阅者,我只希望在该对象的数组元素发生更改时得到通知。

实际上我想要的是redux已经在做的事情了。在redux中,我可以订阅商店,但只选择子元素。

我想为我的后端websocket服务器应用程序实现相同的基础结构。

如何使用RxJS实现这一目标?

2 个答案:

答案 0 :(得分:5)

使用 distinctUntilChanged 运算符。 (docs)

让我们假设对象的结构是:

{
  articleId: 0,
  comments: [ 'lorem', 'ipsum' ]
}

我们想要像firebase那样酷,所以当更新的对象有不同的数组时,我们会实时更新注释。

我正在使用RxJS5进行observable和lodash来比较数组,因为运算符的默认行为不会按照我们希望它们进行比较的方式对它们进行比较。

// Our BehaviorSubject which emits new object.
// For those who don't know: it'll emit the latest emitted value when subscribing to it.
const object$ = new Rx.BehaviorSubject({
  articleId: 0,
  comments: [],
}); 

// If you want specific parts of your application 
// to react only when a specific part of the object has changed, you 
// have to create another observable using 'map' and 
// 'distinctUntilChanged' operator and subscribe to it.
const comments$ = object$
  .map(object => object.comments) // we want to emit comments only
  .distinctUntilChanged((a, b) => _.isEqual(a, b)); // emit only when currently emitted value is different than previous one.

comments$.subscribe(v => console.log(v)); // log fresh comments

object$.next({
  articleId: 1,
  comments: [],
});

object$.next({
  articleId: 1,
  comments: ['lorem', 'ipsum'],
});

object$.next({
  articleId: 2,
  comments: ['lorem', 'ipsum'],
});

object$.next({
  articleId: 2,
  comments: ['lorem', 'ipsum', 'dolor', 'sit', 'amet'],
});

效果:

[]
["lorem", "ipsum"]
["lorem", "ipsum", "dolor", "sit", "amet"]
没有distinctUntilChanged运算符的

效果:

[]
[]
["lorem", "ipsum"]
["lorem", "ipsum"]
["lorem", "ipsum", "dolor", "sit", "amet"]

JSFiddle

答案 1 :(得分:-1)

我们可以根据条件部分订阅源observable(在您的情况下为复杂对象)来解决它。

Rxjs takeWhile有助于实现这一目标。 只有在满足某个条件时才能进行订阅,然后处理发出的输出。

https://www.learnrxjs.io/operators/filtering/takewhile.html