如何获得以前的价值主题?

How to get previous value Subject?

我有以下主题:

  private active = new Subject<P>();
  prev: Custom<any>;

  set(p: P): void {
    this.active.next(p);
  }

我想从 active 主题中提取数据并将其设置为 prev,如下所示:

 set(p: P): void {
     this.prev = this.active;
     this.active.next(p);
 }

怎么做?

你最好在这里使用 BehaviorSubject。它保存当前值,也有 value getter 来获取它。

private active = new BehaviorSubject<P>(null);  // <-- default value required
prev: Custom<any>;

set(p: P): void {
  this.prev = this.active.value;
  this.active.next(p);
}

但这实际上看起来并不那么干净。您打算如何使用 prev 值?也许有一种更简洁的方法,将 ReplaySubject 与缓冲区 2 结合使用。

更新:避免同步.valuegetter

我可以想出 2 种方法来使用流中的先前值。

  1. 直接使用 pairwise 运算符。它会将最后一个值和当前值作为数组发出。不利的一面是它不会发出第一个值,因为还没有当前的先前状态。可以使用 startWith 运算符进行调整。
import { Subject } from "rxjs";
import { startWith, pairwise} from "rxjs/operators";

export class AppComponent {
  subSource = new Subject<any>();
  sub$ = this.subSource.pipe(
    startWith(null),
    pairwise()
  );

  constructor() {
    this.sub$.subscribe(val => console.log("pairwise:", val));

    this.subSource.next(1);
    this.subSource.next(2);
    this.subSource.next(3);
  }
}

// expected output:
// pairwise: [null, 1]
// pairwise: [1, 2]
// pairwise: [2, 3]
  1. 如果您不希望在开始时使用默认值,您可以将 ReplaySubject 与缓冲区 2 一起使用,并使用 scan 运算符仅发出先前和当前值。
import { ReplaySubject } from "rxjs";
import { scan } from "rxjs/operators";

export class AppComponent {
  replaySubSource = new ReplaySubject<any>(2);
  replaySub$ = this.replaySubSource.pipe(
    scan((acc, curr) => {
      acc.push(curr);
      return acc.slice(-2);
    }, [])
  );

  constructor() {
    this.replaySub$.subscribe(val => console.log("replay subject:", val));

    this.replaySubSource.next(1);
    this.replaySubSource.next(2);
    this.replaySubSource.next(3);
  }
}

// replay subject: [1]
// replay subject: [1, 2]
// replay subject: [2, 3]

工作示例:Stackblitz

关于默认值使用find的问题。不,我不认为在那里使用 find 很脏。事实上,find 是根据谓词获取特定元素的,所以我看不出您的用法有任何错误。

更新:作为 {prev: .., active: ..}.

发出

您只需要将 map 运算符通过管道传递到最后并根据要求发出。

sub$ = this.subSource.pipe(
  startWith(null),
  pairwise(),
  map(([prev, active]) => ({ prev: prev, active: active }))
);

// expected output:
// pairwise: {prev: null, active: 1}
// pairwise: {prev: 1, active: 2}
// pairwise: {prev: 2, active: 3}

我还调整了 Stackblitz 以反映这些变化。