我想要一个可以推送减速器功能的流。每次按下reducer函数时,都应该将状态对象传递给reducer,reducer应返回修改后的状态值,并且应该将更新后的状态推送给订阅者。我希望我的代码可以解释:
import Rx from 'rx';
import { Map } from 'immutable';
let initialState = Map({ counter: 0 });
export let upstream = new Rx.BehaviorSubject(Rx.helpers.identity);
export let downstream = upstream.scan((state, reducer) => {
return reducer(state);
}, initialState);
let increment = state => {
return state.update('counter', counter => counter + 1);
};
upstream.onNext(increment);
downstream.subscribe(state => {
console.log('subscriptionA', state.get('counter'));
});
upstream.onNext(increment);
setTimeout(() => {
downstream.subscribe(state => {
console.log('subscriptionB', state.get('counter'));
});
}, 3000);
这是我看到的输出:
subscriptionA 1
subscriptionA 2
subscriptionB 1
虽然我希望看到:
subscriptionA 1
subscriptionA 2
subscriptionB 2
显然我在这里遗漏了一些基本的东西。似乎BehaviorSubject
应该保留新订阅者的最新价值,这会让我认为当subscriptionB
订阅downstream
时它会获得最新的减少价值,但它看起来像中间有.scan
犯规的东西......或其他东西。
这里发生了什么以及如何实现我想要完成的目标?谢谢!
答案 0 :(得分:3)
如果您更换
,您是否可以尝试查看一切是否符合您的期望?export let downstream = upstream.scan((state, reducer) => {
return reducer(state);
}, initialState);
通过
export let downstream = upstream.scan((state, reducer) => {
return reducer(state);
}, initialState).shareReplay(1);
jsfiddle here:http://jsfiddle.net/cqaumutp/
如果是这样,你是Rx.Observable
的热与冷性质的另一个受害者,或者更准确地说是可观察者的懒惰实例化。
简而言之(并非如此简短),每次执行subscribe
时会发生什么,是通过向运营商链上游创建一系列可观察量。每个运算符都订阅其源,并将另一个observable返回到起始源。在您的情况下,当您订阅scan
时,scan
订阅upstream
,这是最后一个。 upstream
作为主题,在订阅时它只注册订阅者。其他来源可以做其他事情(比如在DOM节点或套接字上注册监听器,或其他任何东西)。
这里的要点是,每次订阅scan
时,都会重新开始,即使用initialState
。如果要使用第一次订阅scan
的值,则必须使用share
运算符。在第一次订阅share
时,它会将您的订阅请求传递给scan
。在第二个及后续的那个,它将不会,它将注册它,并转发给相关的观察者所有来自scan
首先订阅的值。
答案 1 :(得分:0)
我有一个解决方案似乎正在给我我想要的结果。如果其他人能够证明它是一个合适的解决方案,我将不胜感激。
import Rx from 'rx';
import { Map } from 'immutable';
let initialState = Map({ counter: 0 });
export let upstream = new Rx.Subject();
let downstreamSource = upstream.scan((state, reducer) => {
return reducer(state);
}, initialState);
export let downstream = new Rx.BehaviorSubject(initialState);
downstreamSource.subscribe(downstream);
let increment = state => {
return state.update('counter', counter => counter + 1);
};
upstream.onNext(increment);
downstream.subscribe(state => {
console.log('subscriptionA', state.get('counter'));
});
upstream.onNext(increment);
setTimeout(() => {
downstream.subscribe(state => {
console.log('subscriptionB', state.get('counter'));
});
}, 3000);