Angular RxJS Observable:takeUntil 与使用订阅取消订阅
Angular RxJS Observable: takeUntil vs. unsubscribe with a Subscription
有几种方法可以取消订阅 Angular 组件上的可观察对象(通过使用 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();
}
}
选项 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:?
- 选项 1:简洁明了。很有魅力
- 选项 2:更程序化,更少流式。奇迹般有效。请注意,您的流不会收到可能导致意外行为的 'complete' 事件
- 选项 3:takeWhile - 将保留订阅直到创建发射,然后评估 takeWhile。这可能会导致意外行为。尽管如此,最终还是有效
TLDR;这里没有错。选择您认为适合您的需求并传达您的意图的内容。
Ben Lesh 也写了一篇很好的文章 post 关于不同的退订方式 https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87
他的意见:
You should probably be using operators like takeUntil
to manage your RxJS subscriptions. As a rule of thumb, if you see two or more subscriptions being managed in a single component, you should wonder if you could be composing those better.
我个人也是选择方案1,即使用takeUntil
。
但是,将 takeUntil()
运算符放在管道序列的最后一个 RxJS 运算符上很重要,如 here 所述。
例如,如果我们不将 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 在取消订阅可观察对象的不同方式(包括 unsubscribe()
和 takeUntil()
运算符)上写了一篇非常好的 article。我也推荐你看看。
对于您的示例,我不会选择这 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 组件上的可观察对象(通过使用 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();
}
}
选项 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:?
- 选项 1:简洁明了。很有魅力
- 选项 2:更程序化,更少流式。奇迹般有效。请注意,您的流不会收到可能导致意外行为的 'complete' 事件
- 选项 3:takeWhile - 将保留订阅直到创建发射,然后评估 takeWhile。这可能会导致意外行为。尽管如此,最终还是有效
TLDR;这里没有错。选择您认为适合您的需求并传达您的意图的内容。
Ben Lesh 也写了一篇很好的文章 post 关于不同的退订方式 https://medium.com/@benlesh/rxjs-dont-unsubscribe-6753ed4fda87
他的意见:
You should probably be using operators like
takeUntil
to manage your RxJS subscriptions. As a rule of thumb, if you see two or more subscriptions being managed in a single component, you should wonder if you could be composing those better.
我个人也是选择方案1,即使用takeUntil
。
但是,将 takeUntil()
运算符放在管道序列的最后一个 RxJS 运算符上很重要,如 here 所述。
例如,如果我们不将 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 在取消订阅可观察对象的不同方式(包括 unsubscribe()
和 takeUntil()
运算符)上写了一篇非常好的 article。我也推荐你看看。
对于您的示例,我不会选择这 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>