Angular RxJS Observable:takeUntil 与使用订阅取消订阅

Hor*_*ley 17 unsubscribe observable rxjs angular

有几种方法可以取消订阅 Angular 组件上的 observables(通过使用 ngOnDestroy)。应首选以下哪个选项?为什么(例如技术原因、性能等)?

选项 1:takeUntil

使用 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();
  }
}

Run Code Online (Sandbox Code Playgroud)

选项 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();
  }
}
Run Code Online (Sandbox Code Playgroud)

选项 3: takeWhile

使用 RxJS takeWhile 取消订阅

选项 n:?

Mar*_*ten 10

  • 选项 1:干净和明确。奇迹般有效
  • 选项 2:更多的程序,更少的流。奇迹般有效。请注意,您的流不会收到可能导致意外行为的“完成”事件
  • 选项 3:takeWhile - 将保持订阅,直到创建发射,然后评估 takeWhile。这可能会导致意外行为。尽管如此,最终还是有效的

TLDR;这里没有错。选择您所看到的适合您的需求并传达您的意图。

Ben Lesh 还写了一篇关于取消订阅的不同方法的好文章https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87

他的意见:

您可能应该使用运算符takeUntil来管理您的 RxJS 订阅。根据经验,如果您看到在单个组件中管理两个或更多订阅,您应该想知道是否可以更好地组合这些订阅。


wen*_*jun 7

就个人而言,我也选择选项 1,即使用takeUntil.

然而,重要的是你放置takeUntil()在管道上序列中的最后RxJS操作运算符,如解释在这里

例如,如果我们不takeUntil()作为最后一个操作员放置,则订阅者将继续订阅后续switchMap()操作员:

this.flightService.getAll()
  .pipe(
    takeUntil(this.destroy$),
    switchMap(() => this.doSomethingElse()),
  ).subscribe(flights => (this.flights = flights));
Run Code Online (Sandbox Code Playgroud)

因此,这样做的正确方法是:

this.flightService.getAll()
  .pipe(
    switchMap(() => this.doSomethingElse()),
    takeUntil(this.destroy$),
  ).subscribe(flights => (this.flights = flights));
Run Code Online (Sandbox Code Playgroud)

Brian Love 写了一篇关于取消订阅可观察对象的不同方式(包括unsubscribe(), 和takeUntil()操作符)的非常好的文章。我也建议你看看它。