我创建了一个Observable,可生成无限量的数据(例如计时器)。这些数据是通过一个主题访问的,因此多个观察者将获得相同的值。
如何停止Observable生成新值? (无需修改Observable的实现)
// custom Observable, to visualize internal behavior
const timer$ = new rxjs.Observable(subscriber => {
console.log("observable init");
var counter = 0;
const intervalId = setInterval(() => {
++counter;
console.log("observable %s",counter);
subscriber.next(counter);
}, 1000);
return () => {
console.log("observable teardown");
clearTimeout(intervalId);
}
});
// subscribe through a subject
const subject$ = new rxjs.Subject();
timer$.subscribe(subject$);
const subscription = subject$.subscribe(value => console.log("observer %s", value));
// cancel subscription
setTimeout(() => {
console.log("unsubscribe observer");
subscription.unsubscribe();
// TODO how to stop Observable generating new values?
}, 3000);
jsfiddle:https://jsfiddle.net/gy4tfd5w/
答案 0 :(得分:2)
幸运的是,在RxJS中有一种专用且优雅的方法可以解决此问题。
您的要求是拥有
多个观察者[...]接收相同的值
这称为可观察的多播,并且有某些运算符用于从普通的“冷”可观察对象中创建一个。
例如,您可以直接将可观察到的源传递给Subject
运算符,而不是直接创建share
的实例,而是为您创建Subject
。 share
的文档内容为:
返回一个新的Observable,它多播(共享)原始Observable。只要有至少一个订户,该Observable便会被预订并发出数据。当所有订阅者都取消订阅后,它将从源Observable取消订阅。
最后一句话显示了share
和source$.subscribe(subject)
之间的细微差别。使用share
可以保留所谓的refCount
,当没有订阅者时,它会自动从其来源退订Subject
。
应用于您的代码,如下所示:
const timer$ =
new rxjs.Observable(subscriber => {// your unchanged implementation})
.pipe(
share()
);
const subscription = timer$.subscribe(value => console.log("observer %s", value));
以下是带有示例代码的完整版本:
https://jsfiddle.net/50q746ad/
顺便说一句,share
不是唯一执行多播的运营商。 There are great learning resources对该主题进行了更深入的介绍。
答案 1 :(得分:0)
这是我阻止疯狂的可观察中间流程的解决方案。
通过使用信号Subject
和rxjs运算符:takeUntil
示例
const stopSignal$ = new Subject();
infinitelyGenerating$
.pipe(takeUntil(stopSignal$))
.subscribe(val => {
if (val === 'bad') {
stopSignal$.next()
}
})
答案 2 :(得分:-1)
因此,在进行了一些惩罚研究之后,我为这个问题添加了自己的npm库。
Improves previous answer by NOT having to add any extra convolution variables and ease of use.