RXJS - BehaviorSubject:正确使用 .value [英] RXJS - BehaviorSubject: proper use of .value

查看:17
本文介绍了RXJS - BehaviorSubject:正确使用 .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.

reactivex.io

您已经在使用 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屋!

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