Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Rx行为主体&x2B;扫描将以前的事件推送到新订户?_Javascript_Rxjs - Fatal编程技术网

Javascript Rx行为主体&x2B;扫描将以前的事件推送到新订户?

Javascript Rx行为主体&x2B;扫描将以前的事件推送到新订户?,javascript,rxjs,Javascript,Rxjs,我想有一个流,我可以推动减速器功能。每次推送reducer函数时,都应将状态对象传递给reducer,reducer应返回修改后的状态值,更新后的状态应推送给订阅服务器。我希望我的代码可以解释: import Rx from 'rx'; import { Map } from 'immutable'; let initialState = Map({ counter: 0 }); export let upstream = new Rx.BehaviorSubject(Rx.helpers.

我想有一个流,我可以推动减速器功能。每次推送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
显然,我在这里遗漏了一些基本的东西。似乎<代码>行为主题< /代码>应该保留新用户的最新值,这将使我认为当<代码>订阅pB/<代码>订阅<代码>下游< /代码>时,它将得到最新的缩减值,但它看起来像是<代码>。
这里发生了什么,我如何完成我想要完成的事情?谢谢

我有一个解决方案,它似乎给了我想要的结果。如果其他人能证明这是一个合适的解决方案,我将不胜感激

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);

如果你更换了,你能试着看看是否一切都符合你的期望吗

export let downstream = upstream.scan((state, reducer) => {
  return reducer(state);
}, initialState);

请点击此处:

如果是这样的话,你是另一个热与冷的受害者,这是
Rx.Observable
,或者更准确地说是观察对象的惰性实例化

简而言之(不是很短),每次你订阅一个
时发生的事情是,一个观察链是通过向操作符链的上游移动而创建的。每个操作符订阅它的源,并返回另一个可观察到的源。在您的情况下,当您订阅
scan
时,
scan
订阅
上游
,这是最后一个<代码>上游
作为主题,订阅时只注册订户。其他源会做其他的事情(比如在DOM节点上注册侦听器,或者套接字,等等)


这里的要点是,每次订阅
扫描
,您都会重新开始,即使用
初始状态
。如果要使用从第一次订阅到
扫描
的值,必须使用
共享
运算符。在第一次订阅
共享
时,它会将您的订阅请求传递到
扫描
。在第二次和后续的扫描中,它将不会对其进行注册,并将来自首次订阅的
扫描的所有值转发给相关的观察者。

感谢您的回复。如果我添加
share()
,那么结果是:
subscriptiona1
subscriptiona2
我没有通过subscriptionB获得任何事件。我认为你的描述有些道理,而且很有帮助。没错,因为
共享
你不再触及行为主题。。。但是,如果您在下一个勾选中发送了其他内容,并使用
upstream.onNext
,您应该会看到它,尽管这并不能解决您的问题。然后,我能想到的是将你放入的
shareReplay(1)
中的
share
替换掉。可惜没有
jsfiddle
我会在我这边玩它。如果这样做有效,那么你就不需要更多的行为主题了。
shareReplay(1)
似乎可以做到这一点。参见这里的jsfiddle。快速单击增量按钮四次,然后等待超时过期,您应该会看到具有正确值的订阅B。正如您所见,您不再需要行为主题,重播将取代大部分功能。您是对的。这很有启发性,也很有道理。感谢您,也感谢您投入工作来制作JSFIDLE!
export let downstream = upstream.scan((state, reducer) => {
  return reducer(state);
}, initialState).shareReplay(1);