2017-07-04 35 views
1

我有一個擁有子對象和數組等的複雜對象。RxJS Observable:當對象的特定部分發生變化時發出

我可以很容易地從這個對象創建一個Subject/BehaviourSubject或Observable,這樣我就可以「向下」(發出)新的狀態給訂閱者。

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

不過,我不希望我的所有用戶將每次通知的對象更改。例如,對於我的一位訂閱者,我只想在該對象的數組元素髮生更改時收到通知。

其實我想要的是REDX已經在做的事情。在REDX中,我可以訂閱商店,但只選擇一個子元素。

我想爲我的後端websocket服務器應用程序實現相同的基礎結構。

如何用RxJS實現這一目標?

+0

我想你不希望在你的應用程序中使用終極版? –

+0

是的,希望。我已經在客戶端運行了REDX(Angular),並且在服務器端我只是希望有一些Rxjs主題來處理它,如果可能的話。 –

+0

像ngrx ['select'](https://github.com/ngrx/core/blob/v1.2.0/src/operator/select.ts)操作符聽起來適合您的用例。 – cartant

回答

3

使用distinctUntilChanged運營商。 (docs)

假設該對象的結構是:

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

我們希望成爲酷派爲火力的傢伙,所以當更新的對象有不同的陣列,我們將更新實時評論。

我使用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'], 
}); 

效果:

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

效果,而distinctUntilChanged操作:

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

JSFiddle

+0

嗨,@ mustafa-ekim。如果此答案解決了您的問題,請考慮將其標記爲已接受,方法是單擊投票數下方的圖標。 –

+0

我認爲_.isEqual(a,b)應該是!_ isEqual(a,b),對嗎? –

+0

根據文檔,它必須返回false才能發出新的值。在這種情況下'_.isEqual(a,b)'是一個有效的比較。 –

-1

我們可以通過根據條件部分訂閱源observable(在您的情況下爲複雜對象)來解決它。

Rxjs takeWhile有助於做到這一點。 只有在滿足特定條件時才能進行訂閱,然後處理髮出的輸出。

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

+0

'takeWhile'將完成你的流,所以它不能真正用於跟蹤原始$ env對象的子樹的所有更改。 –

相關問題