Angular. Когда не надо отписываться в RxJS?
Всегда надо отписываться
Если использовать async pipe, то за вас отпишется Angular. Во всех остальных случаях лучше отписываться самостоятельно.
Допускается не отписываться в потоках, где будет гарантировано вызван complete
такие как of
, timer
или http запрос.
В общем случае (http в частности) верно утверждение: если Observable
выполняется дольше, чем живёт его подписка, то отписываться нужно, иначе можно не отписываться. Другими словами, если время http запрос выполнится после destroy компонента, то отписываться надо.
На сегодняшний день наиболее популярны 2 декларативных подхода отписки:
takeUntil
Паттерн takeUntil()
от члена RxJs core team - Nicholas Jamieson
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-inbox',
templateUrl: './inbox.component.html',
})
export class InboxComponent implements OnInit, OnDestroy {
destroy$ = new Subject<void>();
ngOnInit() {
interval(1000)
.pipe(takeUntil(this.destroy$))
.subscribe(val => console.log(val));
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}
takeUntil()
должен быть последним оператором внутри pipe
.
untilDestroyed
Подход от Netanel Basal. Является развитием способа takeUntil
: не требует создания Subject
и вызова у него методов next
и complete
.
import { untilDestroyed } from 'ngx-take-until-destroy';
@Component({
selector: 'app-inbox',
templateUrl: './inbox.component.html',
})
export class InboxComponent implements OnInit, OnDestroy {
ngOnInit() {
interval(1000)
.pipe(untilDestroyed(this))
.subscribe(val => console.log(val));
}
// Хук всегда должен присутствовать в компоненте, даже если пустой
ngOnDestroy() { }
}