说我有一个行为主题,通过一个或两个操作来传递:
const inputNumber = new BehaviorSubject(2);
// The current number can be retrieved with `inputNumber.getValue()`
const numberAfterOperations = inputNumber.pipe(
filter(a => (a+1) % 2), // filter out odd numbers
map(a => a * a), // square it
);
如何获取numberAfterOperations的值?
// Does not work because `getValue` is not defined!
numberAfterOperations.getValue(); // I expect this to be 4
inputNumber.next(4);
// Does not work!
numberAfterOperations.getValue(); // I expect this to be 16
注意:这里的可观察订阅工作正常。我在问同步访问
.value
(或.getValue()
)
我在这里注意到了一个类似的问题,但是没有看到解决方法: https://github.com/ReactiveX/rxjs/issues/2378
答案 0 :(得分:1)
我认为您对可观察对象/主题的工作方式感到困惑。在您显示的示例中,主题不保留4或16的值,这些值是派生的通过对结果可观察对象应用管道操作来实现的。您必须使用first()
或take(1)
之类的运算符才能在对主题的next
调用之间获得值。主题仅知道通过next
通过它发送的值,不知道可能附加到其上的可观察对象决定如何修改该值。
答案 1 :(得分:0)
Observable.pipe()
返回Observable
,因此,如果您想访问实际的BehaviourSubject
,也必须传递它。
const inputNumber = new BehaviorSubject(2);
// The current number can be retrieved with `inputNumber.getValue()`
const numberAfterOperations = inputNumber.pipe(
filter(a => (a+1) % 2), // filter out odd numbers
map(a => a * a), // square it
map(n => [n, inputNumber])
);
// ...later
numberAfterOperations.subscribe(([number, subject]) => {
sbject.next(n/2);
});
但是不应该这样做,您可以清楚地看到反模式。将.next
设置为单独的方法,然后在需要时将其导入。
答案 2 :(得分:0)
Pipe设置了一个新的可观察对象,该对象在被订阅之前不会执行任何操作。只能使用getValue访问值不是行为主题。您必须订阅它,否则它是冷的可观察到的,根本没有数据顺流而下。将console.log放入地图函数中,您会发现如果没有订阅,它甚至都不会被调用。
如果您可以100%确保订阅将同步运行(就像从BehaviorSubject派生的那样),则可以编写一个取消包装函数,但是如果传递异步可观察的结果,则结果将是不可预测的,很可能返回未定义的结果。
const { BehaviorSubject } = rxjs;
const { filter, map } = rxjs.operators;
const inputNumber$ = new BehaviorSubject(2);
const numberAfterOperations$ = inputNumber$.pipe(
filter(a => (a+1) % 2), // filter out odd numbers
map(a => { console.log('mapping'); return a * a; }), // square it
);
inputNumber$.next(4);
console.log('No mapping has happened yet');
console.log(unwrap(numberAfterOperations$));
function unwrap(obs$) {
let value;
const sub = obs$.subscribe(val => { value = val; });
sub.unsubscribe();
return value;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
如果您使用的是Angular,则可以在视图中使用异步管道
{{ numberAfterOperations | async }}
答案 3 :(得分:0)
谢谢大家的回答。您已经帮助我意识到,对于行为主题,没有内置的方法可以完成我想要的事情。我想到了以下几点:
function mapBehaviorSubject(behavior, mapFn) {
const mappedSubject = new BehaviorSubject(mapFn(behavior.getValue()));
behavior.subscribe({
next: value => mappedSubject.next(mapFn(value)),
});
return mappedSubject;
}
这使我具有所需的行为:
const inputNumber = new BehaviorSubject(2);
const numberAfterOperations = mapBehaviorSubject(inputNumber, x => x * x);
这使我可以拥有一个持久的主题,并且其映射值可以与getValue()
同步使用。