订阅观察者的主题

时间:2017-03-21 17:19:42

标签: angular rxjs rxjs5

我有以下简单的代码:

let a: Observable<any> = Observable.from([1,2,3,4,5]).share();
let b: Subject<any> = new Subject();

a.subscribe(b)
a.subscribe(value => console.log("New observable value: " + value));
b.subscribe(value => console.log("New subject value: " + value));

b.next("value1");
b.next("value2");

我看到的唯一控制台行是对于数组中的每个值都具有“New observable value:”的控制台行。如果我注释掉第3行,那么我得到所有“新的可观察值”行和“新主题值”行,但是主题当然不会得到observable(数组的一部分)省略的任何值。

基本问题 - 这是为什么?为什么我的主题没有看到任何数组元素1,2,3,4,5?它订阅了observable,所以它应该得到这些事件(share()应该向所有订阅者广播),但这似乎是我的误解。

我在这里寻找的是对主题进行单一订阅,并查看来自observable的所有值以及通过调用next()发出的任何值。我的代码是错的,还是我试图以错误的方式做事?

2 个答案:

答案 0 :(得分:2)

当您订阅console.log已收到数据的Subject时,您的基本问题就是订阅的顺序。 (查看下面的代码示例,看它是否正在运行)

第二个问题,即next("value1")无效的原因,是因为a.subscribe(b).complete()发出后也会在b上调用1,2,3,4,5

let a = Rx.Observable.from([1,2,3,4,5]).share();
let b = new Rx.Subject();

b.subscribe(value => console.log("New subject value: " + value));
a.subscribe(value => console.log("New observable value: " + value));
a.subscribe(b);
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

一种方式如何解决此问题:请勿订阅完整的Subject,而只需订阅next - 来电。但请记住,这只是一种方式来实现这一点,具体情况可能会有更好的解决方案。

let a = Rx.Observable.from([1,2,3,4,5]).share();
let b = new Rx.Subject();

b.subscribe(value => console.log("New subject value: " + value));
a.subscribe(value => console.log("New observable value: " + value));
a.subscribe(data => b.next(data));

b.next("value1");
b.next("value2");
<script src="https://unpkg.com/rxjs/bundles/Rx.min.js"></script>

答案 1 :(得分:1)

这是主题及其内部状态的经典问题。

当您致电pie: { allowPointSelect: true, cursor: 'pointer', dataLabels: { enabled: true, format: '<b>{point.name}</b>: {point.percentage:.1f} %', useHTML: true } } 时,主题会收到来自源Observable .highcharts-data-label span { word-wrap:break-word; white-space:pre-wrap!important; } 的所有项目以及标记为已停止的a.subscribe(b)通知。您可以在源代码中看到它:https://github.com/ReactiveX/rxjs/blob/master/src/Subject.ts#L86
然后忽略所有其他信号,您可以在此处看到:https://github.com/ReactiveX/rxjs/blob/master/src/Subject.ts#L56

这意味着此Subject实例将永远不会再发出任何内容。这是永远完成的。您可以看到a信号确实是通过complete运算符发送的:

complete

请参阅演示:https://jsbin.com/bepupor/1/edit?js,console

因此,在您的情况下,您希望保护主题do()不接收a.do(val => console.log('do: ' + val), null, () => console.log('do: complete')) .subscribe(b) 通知。您可以通过手动获取和仅推送b信号来执行此操作:

complete

请参阅演示:https://jsbin.com/bepupor/4/edit?js,console

另一个非常类似的问题:Rx.Subject loses events