在打字稿

时间:2017-11-20 10:04:40

标签: typescript rxjs observable system.reactive

我在打字稿中使用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

是否已经实施了类似的东西或更好的方法来解决这个问题?

2 个答案:

答案 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}构建您的ElementElement[]可观察的结果}}。这应该更容易,因为您可以将每个事件视为命令性命令,而不是必须比较数组以进行更改。

答案 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的可观察属性的部分示例。