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?

如何在 Angular 4 中推送到数组的 Observable? RxJS

javascript EventEmitter vs Observable #angular #rxjs