Угловой лучший способ очистить подписки
Есть много способов эффективно обрабатывать несколько подписок в компоненте, у меня есть 2 способа здесь, и я хотел знать, какой из них более эффективен и почему?
Способ 1: использование массива
Шаг 1: создание массива
private subscriptionArray: Subscription[];
Шаг 2: Добавление подписок в массив
this.subscriptionArray.push(this._storeManagementHttp.createStore(newStore).subscribe(resp => {
this._toast.success('New store created');
}));
Шаг 3: повторение каждой подписки и отмена подписки
this.subscriptionArray.forEach(subs => subs.unsubscribe());
Способ 2
Шаг 1: создание новой подписки
private subscriptions = new Subscription();
Шаг 2: Добавление подписок
this.subscriptions.add(this._storeManagementHttp.createStore(newStore).subscribe(resp => {
this._toast.success('New store created');
this._router.navigate(['/store-management']);
}));
Шаг 3: Очистка подписки
this.subscriptions.unsubscribe();
6 ответов
Вы также можете это, вам не нужно запускать цикл в этом случае
private destroy$ = new Subject();
myservice.megohd().pipe(takeUntil(destroy$)).subscribe();
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
читать здесь ( https://www.learnrxjs.io/operators/filtering/takeuntil.html)
У вас также есть третий вариант - пользовательский оператор RxJS.
Я создал один и узнал, что Нетанель Базаль тоже нашел его, поэтому я дам его чистый код.
Вы можете установить BeforeDestroyed или использовать код:
function isFunction(value) {
return typeof value === 'function';
}
export const untilDestroyed = (
componentInstance,
destroyMethodName = 'ngOnDestroy'
) => <T>(source: Observable<T>) => {
const originalDestroy = componentInstance[destroyMethodName];
if (isFunction(originalDestroy) === false) {
throw new Error(
`${
componentInstance.constructor.name
} is using untilDestroyed but doesn't implement ${destroyMethodName}`
);
}
if (!componentInstance['__takeUntilDestroy']) {
componentInstance['__takeUntilDestroy'] = new Subject();
componentInstance[destroyMethodName] = function() {
isFunction(originalDestroy) && originalDestroy.apply(this, arguments);
componentInstance['__takeUntilDestroy'].next(true);
componentInstance['__takeUntilDestroy'].complete();
};
}
return source.pipe(takeUntil<T>(componentInstance['__takeUntilDestroy']));
};
Тогда ваши подписки становятся
this.myService.subject.pipe(untilDestroyed(this)).subscribe(...);
Обратите внимание, что из-за компиляции AOT, вы должны написать ngOnDestroy
метод, в противном случае оператор не может создать его с нуля.
Есть лучшее, более лаконичное решение: https://www.npmjs.com/package/subsink от Ward Bell.
export class SomeComponent implements OnDestroy {
private subs = new SubSink();
...
this.subs.sink = observable$.subscribe(...);
this.subs.sink = observable$.subscribe(...);
this.subs.sink = observable$.subscribe(...);
...
// Unsubscribe when the component dies
ngOnDestroy() {
this.subs.unsubscribe();
}
}
Способ 2, потому чтоSubscription.unsubscribe()
делает больше, чем просто кажущаяся отписка, см. его исходный код здесь .
например
class SomeClass implements OnInit, OnDestroy { {
// Setup your subscriptions
private subscriptions = new Subscription();
// Example Observable service
constructor(private someService: SomeService) {}
ngOnInit(): void {
this.subscriptions.add(this.someService.getStuff());
// ...
this.subscriptions.add(/* etc */);
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
}
У вас есть хорошие ответы, хотя я бы постарался избежать всех вышеперечисленных методов, если это возможно, и пошел бы на
async
'pipe, то есть разрешить angular выполнять подписку и отмену подписки.
Давайте рассмотрим несколько наблюдаемых, скажем, 5 наблюдаемых.
observale1$: Observable<IDataDto1>;
observale2$: Observable<IDataDto2>;
observale3$: Observable<IDataDto3>;
observale4$: Observable<IDataDto4>;
observale5$: Observable<IDataDto5>;
Чтобы не подписываться на все это, мы можем создать один единственный
Observable
сказать
v$
import { forkJoin } from 'rxjs';
v$ = forkJoin({
observale1: observale1$,
observale2: observale2$,
observale3: observale3$,
observale4: observale4$,
observale5: observale5$
});
С помощью вышеизложенного мы можем обернуть наш component.html в
*ngIf
и разрешить angular автоматически подписываться и отписываться
<ng-container *ngIf='v$ | async as v'>
<!-- Your html code here -->
</ng-container>
Я бы предпочел метод 2.
По методу 1 проблем нет.
Работает отлично. Проблема этого подхода в том, что мы смешиваем наблюдаемые потоки с простой старой императивной логикой.
Метод 2 является встроенным механизмом для улучшения этого подхода.
Читайте здесь