如何给RxJS可观察管道访问原始可观察发射和管道先前的排放?

时间:2018-11-10 02:58:17

标签: angular rxjs angularfire2 rxjs-pipeable-operators immer.js

我有一个RxJS Observable,它发出了对基础数据结构(特别是snapshotChanges() from an AngularFirestoreCollection)的一系列更改。

  • 我目前正在将此映射到普通JavaScript对象数组,以供我的应用使用。
  • 此数组不受任何保护,使用代码可能会意外修改此结构。
  • 每当底层数据源发出信号时,即使实际上仅更改了一项(有时甚至没有),整个数组都会重建。
  • 因此,所有引用每次都会更改,从而使更改检测变得比实际需要更加困难,并且确实减慢了我的应用程序的速度。

我想做的是使用Immer来维护一个不变的结构,以使未更改的数据在结构上与“新”数组共享。

我无法解决的问题是如何pipe()离开snapshotChanges()可观察到的位置,以便管道可以访问以前发出的不可变数据(或首次使用默认值)除了最新的snapshotChanges()输出。

在代码中,我基本上已经有了:

const docToObject = (doc) => { /* change document to fresh plain object every time */ };
const mappedData$ = snapshotChanges().pipe(
    map(changes => changes.map(change => docToObject(change.payload.doc)),
    tap(array => console.log('mutable array:', array)),
);

而我本质上是在寻找类似的东西,而我不知道XXX(...)应该是什么:

const newImmutableObject = (changes, old) => {
  // new immutable structure from old one + changes, structurally sharing as much as
  // possible
};
const mappedData$ = snapshotChanges().pipe(

// ==================================================================================
    XXX(...), // missing ingredient to combine snapshotChanges and previously emitted
              // value, or default to []
// ==================================================================================

    map(([snapshotChanges, prevImmutableOutput]) => newImmutableOutput(...)),
    tap(array => console.log('IMMUTABLE ARRAY with shared structure:', array)),
);

我觉得the expand operator接近我的需要,但似乎只在后续运行中传递先前发出的值,而我还需要新发出的snapshotChanges

鉴于RxJS可观测管道,我如何在可观测管道的排放上进行操作,同时还能访问管道的先前排放?

1 个答案:

答案 0 :(得分:1)

根据您的要求,我建议使用scan运算符,该运算符可以跟踪所有先前状态和新状态。

const newImmutableObject = (changes, old) => {
  // new immutable structure from old one + changes, structurally sharing as much as
  // possible
};
 const mappedData$ = snapshotChanges().pipe(
 scan((acc, current) => [...acc, current], []), //<-- scan is used here
 map(([snapshotChanges, prevImmutableOutput]) => newImmutableOutput(...)),
    tap(array => console.log('IMMUTABLE ARRAY with shared structure:', array)),
);