Angular RxJS Observable:takeUntil 与使用订阅取消订阅 [关闭]
Posted
技术标签:
【中文标题】Angular RxJS Observable:takeUntil 与使用订阅取消订阅 [关闭]【英文标题】:Angular RxJS Observable: takeUntil vs. unsubscribe with a Subscription [closed] 【发布时间】:2020-02-14 03:34:02 【问题描述】:有几种方法可以取消订阅 Angular 组件上的 observables(使用 ngOnDestroy)。应该首选以下哪个选项以及为什么(例如技术原因、性能等)?
选项 1:采取Until
使用 RxJS takeUntil 取消订阅
@Component(
selector: "app-flights",
templateUrl: "./flights.component.html"
)
export class FlightsComponent implements OnDestroy, OnInit
private readonly destroy$ = new Subject();
public flights: FlightModel[];
constructor(private readonly flightService: FlightService)
ngOnInit()
this.flightService
.getAll()
.pipe(takeUntil(this.destroy$))
.subscribe(flights => (this.flights = flights));
ngOnDestroy()
this.destroy$.next();
this.destroy$.complete();
选项 2:.unsubscribe()
显式调用 .unsubscribe(),例如通过使用单独的订阅实例
@Component(
selector: "app-flights",
templateUrl: "./flights.component.html"
)
export class FlightsComponent implements OnDestroy, OnInit
private readonly subscriptions = new Subscription();
public flights: FlightModel[];
constructor(private readonly flightService: FlightService)
ngOnInit()
const subscription = this.flightService
.getAll()
.subscribe(flights => (this.flights = flights));
this.subscriptions.add(subscription);
ngOnDestroy()
this.subscriptions.unsubscribe();
选项 3:takeWhile
使用 RxJS takeWhile 取消订阅
选项 n:?
【问题讨论】:
你可以问十个人,他们都有自己的喜好。您提到的所有选项都是完全有效的,并且没有明确的“最佳”选项。 IMO takeUntil 是最好的解决方案。 好的,我想知道一个或另一个选项是否有技术原因...感谢您的评论 @HoraceP.Greeley 我知道已经晚了,但为什么需要 this.destroy$.next();在选项 1 上? @raberana next() 是必需的,因为“takeUntil”通过调用 destory$.next() 直到 destroy$ 具有值。另一个主题,但很重要:takeUntil 应该在管道中的最后一个位置。见cartant.medium.com/rxjs-avoiding-takeuntil-leaks-fb5182d047ef 【参考方案1】: 选项 1:简洁明了。像魅力一样工作 选项 2:更程序化,更少流式。奇迹般有效。请注意,您的直播不会收到可能导致意外行为的“完成”事件 选项 3:takeWhile - 将保留订阅,直到创建发射,然后评估 takeWhile。这可能导致意外行为。尽管如此,最终还是有效的TLDR;这里没有错。选择您认为适合您的需求并传达您的意图的内容。
Ben Lesh 还写了一篇关于退订https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87 的不同方式的好文章
他的意见:
您可能应该使用像
takeUntil
这样的运算符来管理您的 RxJS 订阅。根据经验,如果您看到在一个组件中管理两个或多个订阅,您应该想知道是否可以更好地组合这些订阅。
【讨论】:
在使用takeUntil
时,我们应该在ngOnDestroy()
中使用this.destroy$.next()
和this.destroy$.complete()
吗?
takeUntil
需要发射,所以你必须next()
一些东西(即使undefined)
。complete()
是多余的,因为没有人在听那个事件。
是不是说我们在使用takeUntil的时候在ngOnDestroy()中不需要this.destroy$.next()和this.destroy$.complete()?【参考方案2】:
就个人而言,我也选择了选项1,即使用takeUntil
。
但是,如here 所述,将takeUntil()
运算符放在管道序列的最后一个RxJS 运算符上很重要。
例如,如果我们不将takeUntil()
作为最后一个运算符,则订阅者将继续订阅后续的switchMap()
运算符:
this.flightService.getAll()
.pipe(
takeUntil(this.destroy$),
switchMap(() => this.doSomethingElse()),
).subscribe(flights => (this.flights = flights));
因此,正确的做法是:
this.flightService.getAll()
.pipe(
switchMap(() => this.doSomethingElse()),
takeUntil(this.destroy$),
).subscribe(flights => (this.flights = flights));
Brian Love 写了一篇非常好的 article,介绍了取消订阅 observables 的不同方式(包括 unsubscribe()
和 takeUntil()
运算符)。我也建议你看看它。
【讨论】:
在使用takeUntil
时,我们应该在ngOnDestroy()
中使用this.destroy$.next()
和this.destroy$.complete()
吗?
@Fredrick 是的,我们应该!抱歉,我的回答没有反映出来。
那么我认为使用unsubscribe
似乎比takeUntil
更好。因为它显示为 showter 版本,但几乎相似,我们也称之为方法onDestroy
。不是吗?
@Fredrick 是的,但是如果您的组件中有多个订阅,使用takeUntil
方法会更干净。相信这篇文章给出了完整的解释medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87
谢谢,但我也阅读了this 文章,发现两种方法在代码长度方面几乎没有区别(其中一种是内部块,另一种是外部块)。【参考方案3】:
对于您的示例,我不会选择 3 个选项中的任何一个。当您只想分配一个值时,然后存储 Observable 并使用异步管道订阅它。
@Component(
selector: "app-flights",
templateUrl: "./flights.component.html"
)
export class FlightsComponent implements OnDestroy, OnInit
public flights$: Observable<FlightModel[]>;
constructor(private readonly flightService: FlightService)
ngOnInit()
this.flights$ = this.flightService.getAll();
<ng-container *ngIf="flights$ | async as flights">
<ng-container *ngFor="let flight of flights">
flight | json
</ng-container>
</ng-container>
【讨论】:
他的示例旨在为问题提供上下文,而您的答案在实际情况下是正确的,但对具体问题并没有真正的帮助。以上是关于Angular RxJS Observable:takeUntil 与使用订阅取消订阅 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
Rxjs 过滤器运算符不适用于 Angular2 Observable
Angular js 2 'node_modules/rxjs/Observable"' 没有导出的成员 'Observable'。导入 Observable
Angular2 RxJS 得到“Observable_1.Observable.fromEvent 不是函数”错误
如何在 Angular/RxJS 中合并两个 observable?