你最好在这里使用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。
更新:避免同步.value getter
我可以想出两种方法来使用流中的前一个值。
-
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]
- 如果您不希望在开头使用默认值,您可以将
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 以反映更改。