angular - 如何让 RxJS 可观察管道访问原始可观察对象的发射和管道的先前发射?
问题描述
我有一个 RxJS Observable,它对底层数据结构发出一系列更改——特别是来自 AngularFirestoreCollection 的 snapshotChanges()。
- 我目前正在将其映射到一组纯 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)),
);
我觉得运算符接近expand
我需要的,但它似乎只在后续运行中传递先前发出的值,而我也需要新发出的snapshotChanges
.
给定一个 RxJS Observable 管道,我怎样才能操作这个 Observable 的排放物,同时还能访问管道之前的排放物?
解决方案
根据您的要求,我建议使用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)),
);
推荐阅读
- c# - 即使元素确实存在,LINQ to XML Elements() 和 Descendants() 也没有产生任何结果
- c++ - 从其他类访问 Qt ui 的最佳方式
- python - 如何保存包括所有权重的 TensorFlow 2 对象检测模型?
- ag-grid - 对列标题上的多个列进行排序,单击 ag-grid
- selenium - 是否可以使用 selenium 网格并行登录具有不同登录 ID 的不同节点?
- java - 我在使用 Retrofit2 的 Android 中的 htttp Post Java 中做错了什么?
- python - 如何在yaml文件中使用另一个键的值
- c# - 将现有对象注入 asp.net web api 2 控制器
- c++ - 读取 malloc()ed 对象中的字符串错误字符时出错。为什么?
- linux - 为什么 ubuntu 20.04 没有运行与从终端手动执行的 QT 启动文件相同的启动文件?