RXJS - BehaviorSubject:正确使用 .value [英] RXJS - BehaviorSubject: proper use of .value
问题描述
我想知道 behaviorSubject.value
是否真的有正确的用法.根据这个答案,我们应该只通过订阅获取价值.
I'm wondering if there is actually a proper use for behaviorSubject.value
. According to to this answer, we should ONLY get values via subscribing.
在我看来没问题的一种情况是,我使用 .value
来确定下一个要推送到流的值,就像我切换一个简单的布尔值一样:
A case where it seems okay to me is where I'm using the .value
in order to determine the next value to push through the stream, like when I'm toggling a simple boolean:
myBoolSubject = new BehaviorSubject(false);
toggle() {
this.myBoolSubject.next(!this.myBoolSubject.value);
}
使用 subscribe()
的替代方法如下:
The alternative using subscribe()
would look like:
toggle() {
this.myBoolSubject.pipe(take(1)).subscribe(
val => this.myBoolSubject.next(!val)
);
}
通过查看 rxjs 源代码 和上述答案,这两种方法之间的区别在于 .value
将在以下情况下抛出:
From looking at the rxjs source and the aforementioned answer, the difference between these two approaches are that .value
will throw when:
- 主题已完成
- 出现错误
在这个简单的例子中,我不会完成这个主题,我不认为错误是一个问题,因为我只是通过这个主题推送简单的布尔值.
In this simple case, I'm not going to complete the subject and I don't think errors are a concern since I'm just pushing simple boolean values through this subject.
这是 behaviorSubject.value
的有效用例吗?还有其他的吗?
Is this a valid use case for behaviorSubject.value
? Are there others?
另一种使用 .value
似乎没问题的情况是从先前发出的值构造一个新对象时:
Another case where it seems okay to use .value
is when constructing a new object from the previously emitted 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);
}
另一种方法是将最新的状态发射缓存在另一个变量中,如下所示:
The alternative would be to cache the latest state emission in another variable, something like this:
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);
}
是否有我忽略的问题?
推荐答案
1.没有 subscribe
和使用 .value
1. boolean example without subscribe
and usage of .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();
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js"></script>
2.响应式编程
避免复杂的有状态程序,在可观察流上使用干净的输入/输出函数.
Avoid intricate stateful programs, using clean input/output functions over observable streams.
您已经在使用 rxjs,您也可以说,您想使用直接命令式代码:
You are already using rxjs where you could also say, you want to use straight imperative code:
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);
.value
对您的代码做了一件与干净的反应式解决方案不同的重要事情.业务逻辑从流的外部移到切换函数中. 正如官方文档所提到的,rxjs 的目标是拥有干净的输入/输出.这意味着您提供给流的每个 input
总是收到相同的 output
.这意味着您的转换应该在流内部处理,没有任何副作用.
The .value
does one important thing to your code that diffs from a clean reactive solution. The business logic is moved outside the stream into the toggle function. As the official docs mention the goal of rxjs is to have clean inputs/outsputs. That means that every input
you are giving your stream receives always the same output
. That means your transformation should be handled inside the stream, without any side-effects.
3.副作用的缺点
- 更难的测试(模拟)
- 难以理解的效果
- 难以扩展的功能(代码建立在动作之上,而不是专注于效果)
4.使用 rxjs 可以更轻松地解决的问题
- 随时间推移的异步/线程数据(取消、暂停、..)
- 运营商
- 轻松组合不同的流(帮助您专注于应该发生的事情而不是什么时候发生)
- 并发(轻松拆分和合并流)
5.我自己的看法
反应式编程为您处理了几个问题,或者至少使它更容易.在你展示的例子中,我看不出你为什么需要使用反应式编程.如果您完全避免 rxjs
和程序 toggle()
完全imperative
,那也完全没问题.但是当您决定使用 BehaviorSubject
时,您决定进行反应式编程.
Reactive programming handles several problems for you, or at least makes it easier. In you shown example I cannot see why you need to use reactive programming. It would be also completely fine if you avoid rxjs
and programm toggle()
fully imperative
. But the moment you dedided going with a BehaviorSubject
you decided going reactive programming.
6.总结
您可以
通过使用.value
来实现您的问题,但您不应该
.
You can
implement your problem by using .value
but you should not
.
这篇关于RXJS - BehaviorSubject:正确使用 .value的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!