【问题标题】:Observing Collections in typescript在打字稿中观察集合
【发布时间】:2017-11-20 10:04:39
【问题描述】:

我在 typescript 中使用 RxJS,并希望有一种通用的方式来处理集合中的更改。一个非常幼稚的实现就像

Observable<Element[]>

集合中的每一个更改都会变成包含所有项目的“广播”。这处理起来非常麻烦(而且可能效率不高),但我主要担心的是它需要在观察者端进行检查发生了什么变化。

假设 Element 的定义如下:

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

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

在这种情况下,我需要某种额外的 Observable 管道操作来接收集合并根据存储的(以前的)值生成一个CollectionChangedEvent,它有一个类型(即AddedRemoved、@ 987654327@) 和一个id(目标元素的)。根据每个元素的哈希计算修改。

class CollectionChangedEvent {
  type: ChangeType,
  id: string
}

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

【问题讨论】:

  • 我从未使用过 RxJS,但例如,redux 通过比较数组是否相同来解决这个问题。顺便说一句,您不应该使用哈希来检查是否发生了变化,因为哈希最终会发生冲突。
  • 你是对的,可能像 elementA.equals(elementB) 这样的东西在这里更合适......只是对解决可观察集合的处理的通用方法感兴趣......
  • 并非如此。如果你想拥有一些可能触发事件的属性,只需使用 setter 而不是普通属性。
  • 我想也许我没有明确说明这一点,但我感兴趣的是基于 Rx 的解决方案来处理集合的变化(我并不真正使用节点)。元素本身不应该发出事件,而是这些元素的容器应该发出。

标签: typescript rxjs observable system.reactive


【解决方案1】:

你看过.scan()吗?我认为这很合适。假设来源是source:Observable&lt;Element[]&gt;,我会这样做:

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 =&gt; Observable.from(arr)

或者你可以考虑做相反的事情,如果你有一个给你CollectionChangedEvent的源流,那么你可以使用scan()来构建ElementElement[]的可观察结果。这应该更容易,因为您可以将每个事件视为命令式命令,而不必比较数组的变化。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-20
      • 1970-01-01
      • 2021-03-06
      • 2020-11-11
      • 2015-11-16
      • 1970-01-01
      • 2018-08-12
      • 1970-01-01
      相关资源
      最近更新 更多