昨天說到了將資料訂閱出來渲染在頁面上的事,那麼就就來說說 RxJs 解訂閱這件事吧。 這也是為了避免 memory leak,或重覆訂閱所造成的 BUG,若非有限訂閱,通常在訂閱離開後,都需要解訂閱。
轉換為的 Observable
first
只執行第一次,通常用於第一次進來讀取成功取得資料後,就不需再次執行
export class RxjsOndestroyComponent implements OnInit, OnDestroy {
private destroy$: Subject<boolean> = new Subject();
private timer$: Observable<number> = timer(0, 1000);
constructor() {}
ngOnInit(): void {
this.timer$.pipe(first()).subscribe((time) => {
console.log('time', time);
this.count = time;
});
}
}
take(1)
只發生一次
export class RxjsOndestroyComponent implements OnInit, OnDestroy {
private destroy$: Subject<boolean> = new Subject();
private timer$: Observable<number> = timer(0, 1000);
constructor() {}
ngOnInit(): void {
this.timer$.pipe(first()).subscribe((time) => {
console.log('time', time);
this.count = time;
});
}
}
takeUntil
持續執行,直到離開
export class RxjsOndestroyComponent implements OnInit, OnDestroy {
private onDestroy$: Subject = new Subject<void>();
private timer$: Observable<number> = timer(0, 1000);
constructor() {}
ngOnInit(): void {
this.timer$.pipe(takeUntil(this.onDestroy$)).subscribe((time) => {
console.log('time', time);
});
}
ngOnDestroy(): void {
this.onDestroy$.next();
this.onDestroy$.complete();
}
}
unsubscribe
export class RxjsOndestroyComponent implements OnInit, OnDestroy {
private subscription: Subscription = new Subscription();
private timer$: Observable<number> = timer(0, 1000);
constructor() {}
ngOnInit(): void {
this.subscription.add(
this.timer$.subscribe((time) => {
console.log('time', time);
})
);
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
}
}
使用 Async Pipe
template
<div>{{ timer$ | async }}</div>
ts
export class RxjsOndestroyComponent implements OnInit, OnDestroy {
timer$: Observable<number> = timer(0, 1000).pipe(
tap((time: number) => console.log('time', time))
);
}
當 component 離開時,AsyncPipe 會自動取消訂閱
有限的 Observable
在 Angular 裡,有一些 Observable 離開後就會自動取消訂閱
裡面包含了:
- HTTP
- router 與 ActivatedRoute
- reactive forms 裡的 valueChanges 與 statusChanges
參考資料: Angular 中的可觀察物件