如何让 RxJS 可观察管道访问原始 observable 的发射和管道的先前发射? [英] How can I give an RxJS observable pipe access to the original observable's emission AND the pipe's previous emission?
问题描述
我有一个 RxJS Observable,它对底层数据结构发出一系列更改——具体来说,snapshotChanges() 来自 AngularFirestoreCollection.
I have an RxJS Observable that emits a series of changes to an underlying data structure—specifically, snapshotChanges() from an AngularFirestoreCollection.
- 我目前正在将其映射到一组纯 JavaScript 对象以供我的应用使用.
- 此数组不受任何保护,使用代码可能会意外修改此结构.
- 只要底层数据源发出,就会重建整个数组,即使数组中只有一项(或有时没有)实际发生了变化.
- 正因如此,所有引用每次都会发生变化,这使得变化检测变得比实际需要的更难——而且真的减慢了我的应用程序的速度.
我想要做的是使用 Immer 来维护一个不可变的结构,这样不变的数据在结构上与新"数组共享.
What I want to do instead is use Immer to maintain an immutable structure, such that unchanged data is structurally shared with the "new" array.
我无法解决的是如何从 snapshotChanges()
observable 中移除 pipe()
以便管道可以访问先前发出的不可变数据(或首次默认)除了最新的snapshotChanges()
输出.
What I can't work out is how to pipe()
off the snapshotChanges()
observable such that the pipe gets access to the previously emitted immutable data (or a first-time default) in addition to the latest snapshotChanges()
output.
在代码中,我基本上已经拥有的是:
In code, what I basically already have is this:
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(...)
应该是什么:
and I'm essentially looking for something like this, where I don't know what XXX(...)
should be:
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)),
);
我觉得自己像 expand
运算符接近我需要的,但它似乎只在后续运行中传递先前发出的值,而我还需要新发出的 snapshotChanges
.
I feel like the expand
operator is close to what I need, but it seems to only pass the previously emitted value in on subsequent runs, whereas I also need the newly emitted snapshotChanges
.
给定一个 RxJS Observable 管道,我该如何操作这个 Observable 的排放,同时还能访问管道之前的排放?
推荐答案
根据您的要求,我建议使用 scan
运算符,它可以跟踪所有以前的状态和新状态.
As per your requirement I would suggest to use scan
operator which can track all previous state and new state.
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)),
);
这篇关于如何让 RxJS 可观察管道访问原始 observable 的发射和管道的先前发射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!