我在打字稿中使用RxJS,并希望有一种通用方法来处理集合中的更改。一个非常天真的实现就像是
Observable<Element[]>
集合中的每一个变化都会变成所有项目的“广播”。这非常麻烦(也可能效率不高),但我主要担心的是它需要检查观察者方面发生了什么变化。
让我们假设Element被定义为:
class Element {
id: string,
propA: string,
propB: string,
hash(): number {..} // generates a hash based on the properties
}
在这种情况下,我希望在添加,删除或修改任何元素时收到通知(如果id
保持不变,则会认为元素被修改,但某些属性不相同)
在这种情况下,我需要某种额外的Observable管道操作来接收集合,并根据存储的(之前的)值生成CollectionChangedEvent
,它有一个类型(即Added
,{ {1}},Removed
)和Modified
(目标元素)。根据每个元素的散列计算修改。
id
是否已经实施了类似的东西或更好的方法来解决这个问题?
答案 0 :(得分:2)
你看过.scan()
了吗?我认为这是合适的。假设源是source:Observable<Element[]>
,我会做类似的事情:
const result:Observable<CollectionChangedEvent[]> = source
.scan((previous, newElements:Element[]) => {
const previousElements:Element[] = previous.elements;
const newChanges = [];
/* [...] Do huge comparison here, pushing each change you find between newElements and previousElements into newChanges */
return {
elements: newElements,
changes: newChanges
}
}, { // Initial values: They are empty arrays
elements: [],
changes: []
})
.map(acc => acc.changes)
这样的事情。如果您需要result
observable为单CollectionChangedEvent
而不是数组,则可以mergeMap
将其arr => Observable.from(arr)
或者您可以考虑使用oposite,如果您有一个为您提供CollectionChangedEvent
的源流,那么您可以使用{{1}构建您的Element
或Element[]
可观察的结果}}。这应该更容易,因为您可以将每个事件视为命令性命令,而不是必须比较数组以进行更改。
答案 1 :(得分:0)
也许这对你来说已经足够了:
class Observable extends EventEmitter {
constructor(protected callback: Function) {
super();
this.on("change", callback);
}
}
class Element extends Observable {
constructor(public id: string, callback: Function) {
super(callback);
}
private _propA: string;
set propA(v: string) {
this.emit("change", {changed: "_propA", newV: v, oldV: this._propA});
this._propA = v;
}
}
这是使用Node的EventEmitter的可观察属性的部分示例。