如何让 RxJS 可观察管道访问原始 observable 的发射和管道的先前发射? [英] How can I give an RxJS observable pipe access to the original observable's emission AND the pipe's previous emission?

查看:22
本文介绍了如何让 RxJS 可观察管道访问原始 observable 的发射和管道的先前发射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆