RXJS-同时使用take(1)和takeUntil()

时间:2019-07-04 17:50:22

标签: angular rxjs rxjs5

在网上搜索后,我发现人们通常会使用一个或另一个,而不是两者都使用。可以同时使用两者吗?这是好事还是坏事?

修改

我不是在问take(1)或takeUntil是做什么用的。而是我在问是否有可能同时具有take(1)和takeUntil的效果。我知道take(1)将仅采用第一个值并结束订阅。但是,如果我从没有收到活动,它将不会终止订阅。我也了解,只要组件不再处于活动状态,只要我在销毁中触发unsubscribeSubject,就可以使用takeUntil来清理订阅。但是,在我收到第一个值后,它不会释放该订阅,并且在该组件处于活动状态的整个过程中都会存在。

我想要的是一种在第一个值之后释放订阅的方法,并防止在组件未激活(如果未收到值)时内存泄漏。特别是在您有许多订阅的情况下。这是因为当您有许多订阅时,只有一个主题可以方便地在不需要该组件时清理所有订阅。

ngAfterViewInit(){
    //if first value comes, we process it and unsubscribe
    this.myService.GetOneTimeObservable()
        .pipe(take(1))
        .pipe(takeUntil(this.unsubscribeSubject))
        .subscribe(this.fooOT.bind(this))

    //other subscriptions (assume many)
    this.myService.GetLongLifeObservable1()
        .pipe(takeUntil(this.unsubscribeSubject))
        .subscribe(this.foo1.bind(this))

    this.myService.GetLongLifeObservable2()
        .pipe(takeUntil(this.unsubscribeSubject))
        .subscribe(this.foo2.bind(this))

    this.myService.GetLongLifeObservable3()
        .pipe(takeUntil(this.unsubscribeSubject))
        .subscribe(this.foo3.bind(this))
}

ngOnDestroy(){
    //Ideally cleans all subscriptions, including the OneTime if no value is received
    this.unsubscribeSubject.next();
    this.unsubscribeSubject.complete();
}

3 个答案:

答案 0 :(得分:1)

简短地说:是的,可以同时使用两者。您可以使用以下示例自行尝试:

import { fromEvent, timer } from 'rxjs'; 
import { map, takeUntil, take } from 'rxjs/operators';

const source = fromEvent(document, 'click');
const destruct = timer(5000);

source.pipe(
  takeUntil(destruct), //the order of take/takeUntil doesn't matter
  take(1),
).subscribe(
  () => console.log('click'),
  () => console.log('error'),
  () => console.log('complete')
); 

在第一次单击或销毁事件(此处由计时器模拟)后即可完成观察。我认为这不是一个坏习惯,但我不是专家。

答案 1 :(得分:0)

不能保证

take(1)取消可观察对象,因为它可能在销毁组件之前没有发出。 takeUntil保证可观察对象不是内存泄漏。如果在组件被销毁之前可观察对象要花很长时间才能发射出去,并且您只有take(1)并转到另一个组件,则订阅仍在侦听并且即使该组件不再处于活动状态也将触发。

使用take(1)的唯一原因是,如果主题可能发出不止一次且您只想要第一个值,则takUntil足以确保没有内存泄漏。

答案 2 :(得分:0)

如果您的思考过程是:“我知道我可以获得多个发射值,但只想要第一个。”和“我可能没有任何值,并且希望取消在组件上取消订阅的订阅。”然后创建一个类变量来存储订阅,并在destroy上取消订阅。

private oneTimeSubscription: Subscription;

ngAfterViewInit(){
  this.oneTimeSubscription = this.myService.GetOneTimeObservable()
    .pipe(take(1))
    .subscribe(this.fooOT.bind(this))
}

ngOnDestroy(){
  this.oneTimeSubscription.unsubscribe();
}

或者您可以在线取消订阅:

ngAfterViewInit(){
  const oneTimeSubscription: Subscription = this.myService.GetOneTimeObservable()
    .pipe(take(1))
    .subscribe(this.fooOT.bind(this, oneTimeSubscription))
}

fooOT(subscription: Subscription): void {
  subscription.unsubscribe();
  // rest of your code here...
}