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

查看:63
本文介绍了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()的替代方法如下:

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
  2. 用法的布尔示例
  1. the 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>

  1. 反应性编程

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

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.

  1. 副作用的缺点

  • 更严格的测试(模拟)
  • 难以理解的效果
  • 难以扩展的功能(代码建立在动作之上,而不是专注于效果)
    1. 使用rxjs可以更轻松地解决问题

    • 随时间推移的异步/线程化数据(取消,暂停,..)
    • 操作员
    • 轻松组成不同的流(帮助您专注于应该发生的事情,而更少地关注何时发生)
    • 并发(轻松拆分和合并流)
      1. 我自己的观点

      响应式编程可以为您解决一些问题,或者至少使它变得更容易.在显示的示例中,我看不到为什么需要使用反应式编程.如果完全避免 rxjs 编程 toggle()完全命令性,那也完全可以.但是,当您决定使用 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.

      1. 总和

      可以通过使用 .value 解决问题,但您不应该.

      You can implement your problem by using .value but you should not.

      这篇关于RXJS-BehaviorSubject:正确使用.value的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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