在网上搜索后,我发现人们通常会使用一个或另一个,而不是两者都使用。可以同时使用两者吗?这是好事还是坏事?
修改
我不是在问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();
}
答案 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...
}