RXJS - BehaviorSubject:正确使用 .value

Biz*_*Bob 10 rxjs angular

我想知道behaviorSubject.value. 根据这个答案,我们应该只通过订阅获得价值。

一个对我来说似乎没问题的情况是我使用.value来确定下一个值来推送流,就像我切换一个简单的布尔值一样:

myBoolSubject = new BehaviorSubject(false);

toggle() {
  this.myBoolSubject.next(!this.myBoolSubject.value);
}
Run Code Online (Sandbox Code Playgroud)

使用的替代方法subscribe()如下:

toggle() {
   this.myBoolSubject.pipe(take(1)).subscribe(
      val => this.myBoolSubject.next(!val)
   );
}
Run Code Online (Sandbox Code Playgroud)

通过查看rxjs 源代码和上述答案,这两种方法之间的区别在于.value

  • 题目已经完成
  • 出现错误

在这个简单的例子中,我不会完成这个主题,我不认为错误是一个问题,因为我只是通过这个主题推送简单的布尔值。

这是一个有效的用例behaviorSubject.value吗?还有其他人吗?

另一种似乎可以使用的情况.value是从先前发出的值构造一个新对象时:

private state = new BehaviorSubject<State>(INITIAL_STATE);
public state$ = this.state.asObservable();

public updateState(changes: Partial<State>){
    const newState = {...this.state.value, ...changes};
    this.state.next(newState);
}

Run Code Online (Sandbox Code Playgroud)

另一种方法是将最新的状态发射缓存在另一个变量中,如下所示:

private _state = INITIAL_STATE;
private state = new BehaviorSubject<State>(INITIAL_STATE);
public state$ = this.state.asObservable();

public updateState(changes: Partial<State>){
    const newState = {...this._state, ...changes};
    this.state.next(this._state = newState);
}
Run Code Online (Sandbox Code Playgroud)

有没有我忽略的问题?

Jon*_*wag 7

  1. 没有subscribe和使用的布尔示例.value

const { Subject } = rxjs;
const { scan, startWith } = rxjs.operators;

myToggle$$ = new Subject();

myBool$ = myToggle$$.pipe(
  scan((acc) => !acc, false),
  startWith(false)
)

myBool$.subscribe(v => console.log('result: ', v));

myToggle$$.next();
myToggle$$.next();
myToggle$$.next();
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

  1. 反应式编程

避免复杂的有状态程序,在可观察流上使用干净的输入/输出函数。

反应式xio

您已经在使用 rxjs,您也可以说,您想使用直接命令式代码:

myBool = false;
function myToggle() { myBool = !myBool }

console.log('result: ', myBool);
myToggle();
console.log('result: ', myBool);
myToggle();
console.log('result: ', myBool);
myToggle();
console.log('result: ', myBool);
Run Code Online (Sandbox Code Playgroud)

.value对您的代码做了一件与干净的反应式解决方案不同的重要事情。业务逻辑被移到流之外的切换函数中。正如官方文档提到的 rxjs 的目标是拥有干净的输入/输出。这意味着input您提供的每个流都收到相同的output. 这意味着您的转换应该在流内部处理,没有任何副作用。

  1. 副作用的缺点
  • 更难的测试(模拟)
  • 难以理解的效果
  • 难以扩展的功能(代码建立在动作之上,而不是专注于效果)
  1. 使用 rxjs 可以更轻松解决的问题
  • 随着时间的推移异步/线程数据(取消,暂停,..)
  • 运营商
  • 轻松组合不同的流(帮助您专注于应该发生的事情以及更少的时间)
  • 并发(轻松拆分和合并流)
  1. 我自己的看法

反应式编程为您处理了几个问题,或者至少使它更容易。在你展示的例子中,我看不出你为什么需要使用反应式编程。如果您完全避免rxjs和编程,那也toggle()完全没问题imperative。但是当BehaviorSubject你决定使用响应式编程的那一刻。

can通过使用.valuebut you来实现您的问题should not


HTN*_*HTN -1

我不知道你的用例,但通常,你不应该toggle()在没有参数的情况下使用,而是设置值:

setValue(v: boolean) {
   this.myBoolSubject.next(v);
}
Run Code Online (Sandbox Code Playgroud)

调用者应该始终知道要设置什么值。在您确实不想给出该值的特殊情况下,使用.value就可以了。