RxJS可观察:当对象的特定部分发生更改时发出

Mus*_*kim 3 rxjs rxjs5

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

我可以轻松地从此对象创建Subject / BehaviourSubject或Observable,以便可以将新状态“下一步”(发射)给订阅者。

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

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

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

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

如何使用RxJS实现呢?

Mic*_*zko 6

使用distinctUntilChanged运算符。(文档)

假设对象的结构为:

{
  articleId: 0,
  comments: [ 'lorem', 'ipsum' ]
}
Run Code Online (Sandbox Code Playgroud)

我们希望像Firebase一样酷,因此当更新的对象具有不同的数组时,我们将实时更新注释。

RxJS5用于可观察对象并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'],
});
Run Code Online (Sandbox Code Playgroud)

影响:

[]
["lorem", "ipsum"]
["lorem", "ipsum", "dolor", "sit", "amet"]
Run Code Online (Sandbox Code Playgroud)

没有distinctUntilChanged运算符的效果:

[]
[]
["lorem", "ipsum"]
["lorem", "ipsum"]
["lorem", "ipsum", "dolor", "sit", "amet"]
Run Code Online (Sandbox Code Playgroud)

JSFiddle