1) Как правило, вам не нужно отписываться при прямом вызове http. Даже если компонент уничтожен, накладные расходы с завершением подписки после уничтожения незначительны. Вам нужно отписаться здесь, если вы быстро переключаете свои компоненты. Отказ от подписки также отменяет запрос http, поэтому, если это необходимо, отмените подписку.
Отмена подписки не приносит никакого вреда. Если вы не уверены, всегда отмените подписку.
2) Вам необходимо отменить подписку при подписке на наблюдаемое, которое не завершается, когда ваш компост уничтожается. В противном случае это может привести к утечке памяти (и производительности). Поскольку сама наблюдаемая содержит ссылку на подписку, а подписка содержит ссылку на компонент, компонент никогда не будет очищен из памяти, и действие, описанное в подписке, будет выполняться до тех пор, пока наблюдаемая не завершится, что в вашем случае никогда не происходит. ,Это будет происходить для каждого экземпляра вашего компонента.
Решения
Я поделюсь двумя популярными вариантами упрощения бремени отказа от подписки. Расширяя ответ @ amanagg1204, вы можете создать базовый компонент, из которого вы будете расширять все ваши будущие компоненты. Вы можете иметь собственный оператор в нем. У этого есть один недостаток - вам всегда нужно вызывать super.ngOnDestroy()
, если вам нужно использовать ngOnDestroy
в вашем компоненте.
import { OnDestroy } from "@angular/core";
import { Subject, MonotypeOperatorFunction } from "rxjs";
import { takeUntil } from "rxjs/operators";
export abstract class UnsubscribeComponent implements OnDestroy {
protected destroyed$: Subject<void> = new Subject();
ngOnDestroy(): void {
this.destroyed$.next();
this.destroyed$.complete();
}
takeUntilDestroyed<T>(): MonoTypeOperatorFunction<T> {
return takeUntil(this.destroyed$);
}
}
export class Component extends UnsubscribeComponent {
ngOnInit() {
this.contacts$.pipe(
this.takeUntilDestroyed(),
).subscribe((data:any[])=>{
this.records = this.sortData(data);
});
}
// WARNING - if you declare your ngOnDestroy in the component
ngOnDestroy() {
// DO NOT FORGET to call this
super.ngOnDestroy();
doYourStuff();
}
}
Другой вариант (мой предпочтительный) - не иметь родительский абстрактный класс(хотя это также может быть реализовано так), но использовать утилиту под названием subsink
(npm i subsink --save
)
import { SubSink } from 'subsink';
export class SampleComponent implements OnInit, OnDestroy {
private subs = new SubSink();
ngOnInit(): void {
// Just put it into sink.
this.subs.sink = this.contacts$.subscribe((data:any[])=>{
this.records = this.sortData(data);
});
// call repeatedly
this.subs.sink = this.otherService$.subscribe((data:any[])=>{
this.things = this.sortData(data);
});
}
ngOnDestroy(): void {
// this will unsubscribe all
this.subs.unsubscribe();
}
}