繁体   English   中英

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

[英]RXJS - Using both take(1) and takeUntil()

在网上搜索后,我看到人们通常使用一种或另一种,而不是两者都使用。 可以同时使用吗? 这是好还是坏的做法?

编辑

我不是在问 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();
}

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

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

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

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

Observable 在第一次单击或销毁事件时完成(此处由计时器模拟)。 在我看来,这不是一个坏习惯,但我不是专家。

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

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...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM