代码之家  ›  专栏  ›  技术社区  ›  marsop

在typescript中观察集合

  •  3
  • marsop  · 技术社区  · 7 年前

    我在typescript中使用RxJS,希望有一种通用的方法来处理集合中的更改。一个非常幼稚的实现类似于

    Observable<Element[]>
    

    收藏中的每一个变化都会变成包含所有物品的“广播”。。处理这个问题非常麻烦(可能效率不高),但我主要担心的是,这需要观察者检查发生了什么变化。

    假设元素的定义如下:

    class Element {
      id: string,
      propA: string,
      propB: string,
      hash(): number {..} // generates a hash based on the properties
    }
    

    在这种情况下,我希望在添加、删除或修改任何元素时收到通知(如果 id 保持不变,但某些属性不相同)。

    在这种情况下,我需要一些额外的可观察管道操作来接收集合,并基于存储的(以前的)值生成一个 CollectionChangedEvent ,它有一个类型(即。 Added , Removed , Modified )和一个 身份证件 (目标元素的)。基于每个元素的哈希计算修改。

    class CollectionChangedEvent {
      type: ChangeType,
      id: string
    }
    

    是否已经实施了类似的措施,或者有更好的方法来实现这一点?

    2 回复  |  直到 7 年前
        1
  •  2
  •   olivarra1    7 年前

    你看过吗 .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 可观察为单一 CollectionChangedEvent 然后,您可以不使用数组 mergeMap 它是为了 arr => Observable.from(arr)

    或者你可以考虑做oposite,如果你有一个提供给你的源流的话 集合更改事件 ,然后您可以建立可观察的结果 Element Element[] 通过使用 scan() . 这应该更容易,因为您可以将每个事件视为命令,而不必比较数组的更改。

        2
  •  0
  •   lilezek    7 年前

    也许这对你来说已经足够了:

    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;
      }
    }
    

    这是使用节点的EventEmitter的可观察属性的部分示例。