rxjs-通过主题订阅停止可观察

时间:2018-12-10 23:59:09

标签: rxjs observable subject unsubscribe

我创建了一个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/

3 个答案:

答案 0 :(得分:2)

幸运的是,在RxJS中有一种专用且优雅的方法可以解决此问题。

您的要求是拥有

  

多个观察者[...]接收相同的值

这称为可观察的多播,并且有某些运算符用于从普通的“冷”可观察对象中创建一个。

例如,您可以直接将可观察到的源传递给Subject运算符,而不是直接创建share的实例,而是为您创建Subjectshare的文档内容为:

  

返回一个新的Observable,它多播(共享)原始Observable。只要有至少一个订户,该Observable便会被预订并发出数据。当所有订阅者都取消订阅后,它将从源Observable取消订阅。

最后一句话显示了sharesource$.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.

enter image description here