什么时候我应该存储订阅实例和调用unsubscribe()在ngOnDestroy生命周期,什么时候我可以简单地忽略它们?
保存所有订阅会给组件代码带来很多麻烦。
HTTP客户端指南忽略这样的订阅:
getHeroes() {
this.heroService.getHeroes()
.subscribe(
heroes => this.heroes = heroes,
error => this.errorMessage = <any>error);
}
同时,《航路指南》指出:
最终,我们会航行到别的地方。路由器将从DOM中移除这个组件并销毁它。在那之前,我们得把自己弄干净。具体来说,我们必须在Angular销毁该组件之前取消订阅。如果不这样做,可能会产生内存泄漏。
我们在ngOnDestroy方法中取消订阅我们的可观察对象。
private sub: any;
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
let id = +params['id']; // (+) converts string 'id' to a number
this.service.getHero(id).then(hero => this.hero = hero);
});
}
ngOnDestroy() {
this.sub.unsubscribe();
}
订阅本质上只有一个unsubscribe()函数来释放资源或取消可观察对象的执行。
在Angular中,当组件被销毁时,我们必须从Observable中取消订阅。幸运的是,Angular有一个ngOnDestroy钩子,它会在组件被销毁之前被调用,这使得开发人员可以在这里提供清理人员,以避免挂起订阅、打开门户,以及将来可能会在背后伤害我们的事情
@Component({...})
export class AppComponent implements OnInit, OnDestroy {
subscription: Subscription
ngOnInit () {
var observable = Rx.Observable.interval(1000);
this.subscription = observable.subscribe(x => console.log(x));
}
ngOnDestroy() {
this.subscription.unsubscribe()
}
}
我们添加了ngOnDestroy到我们的appcomponent,并在这个上调用unsubscribe方法。订阅可观察到的
如果有多个订阅:
@Component({...})
export class AppComponent implements OnInit, OnDestroy {
subscription1$: Subscription
subscription2$: Subscription
ngOnInit () {
var observable1$ = Rx.Observable.interval(1000);
var observable2$ = Rx.Observable.interval(400);
this.subscription1$ = observable.subscribe(x => console.log("From interval 1000" x));
this.subscription2$ = observable.subscribe(x => console.log("From interval 400" x));
}
ngOnDestroy() {
this.subscription1$.unsubscribe()
this.subscription2$.unsubscribe()
}
}
更新Angular 9和Rxjs 6解决方案
在Angular组件的ngDestroy生命周期中使用unsubscribe
class SampleComponent implements OnInit, OnDestroy {
private subscriptions: Subscription;
private sampleObservable$: Observable<any>;
constructor () {}
ngOnInit(){
this.subscriptions = this.sampleObservable$.subscribe( ... );
}
ngOnDestroy() {
this.subscriptions.unsubscribe();
}
}
在Rxjs中使用takeUntil
class SampleComponent implements OnInit, OnDestroy {
private unsubscribe$: new Subject<void>;
private sampleObservable$: Observable<any>;
constructor () {}
ngOnInit(){
this.subscriptions = this.sampleObservable$
.pipe(takeUntil(this.unsubscribe$))
.subscribe( ... );
}
ngOnDestroy() {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
}
你在ngOnInit调用的一些动作,在组件init时只会发生一次。
class SampleComponent implements OnInit {
private sampleObservable$: Observable<any>;
constructor () {}
ngOnInit(){
this.subscriptions = this.sampleObservable$
.pipe(take(1))
.subscribe( ... );
}
}
我们也有async管道。但是,这个是在模板上使用的(不是在Angular组件中)。
出于性能原因,总是建议从你的可观察订阅中取消订阅,以避免内存泄漏,有不同的方法,
顺便说一下,我读了大部分的答案,我没有发现有人在谈论异步管道,推荐在Angular应用中使用Rxjs模式,因为它在离开组件时会自动提供订阅和订阅,而这些订阅将被销毁:
请找到一个如何实现它的例子
app.compoennt.ts:
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { BookService } from './book.service';
import { Book } from './book';
@Component({
selector: 'app-observable',
templateUrl: './observable.component.html'
})
export class AppComponent implements OnInit {
books$: Observable<Book[]>
constructor(private bookService: BookService) { }
ngOnInit(): void {
this.books$ = this.bookService.getBooksWithObservable();
}
}
app.compoennt.html:
<h3>AsyncPipe with Promise using NgFor</h3>
<ul>
<li *ngFor="let book of books$ | async" >
Id: {{book?.id}}, Name: {{book?.name}}
</li>
</ul>
Angular 2官方文档提供了一个关于何时退订以及何时可以安全忽略的解释。看看这个链接:
https://angular.io/docs/ts/latest/cookbook/component-communication.html !# bidirectional-service
寻找标题为“父母和孩子通过服务通信”的段落,然后是蓝色方框:
注意,当AstronautComponent被销毁时,我们捕获了订阅并取消了订阅。这是一个内存泄漏保护步骤。在这个应用程序中没有实际的风险,因为AstronautComponent的生命周期与应用程序本身的生命周期相同。在更复杂的应用程序中,这并不总是正确的。
我们没有将这个守卫添加到MissionControlComponent中,因为作为父组件,它控制着MissionService的生命周期。
我希望这对你有所帮助。
对于每一个订阅,你都需要取消订阅。Advantage =>以防止状态变得过于沉重。
例如:
在组件1中:
import {UserService} from './user.service';
private user = {name: 'test', id: 1}
constructor(public userService: UserService) {
this.userService.onUserChange.next(this.user);
}
在服务:
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
public onUserChange: BehaviorSubject<any> = new BehaviorSubject({});
于component2:
import {Subscription} from 'rxjs/Subscription';
import {UserService} from './user.service';
private onUserChange: Subscription;
constructor(public userService: UserService) {
this.onUserChange = this.userService.onUserChange.subscribe(user => {
console.log(user);
});
}
public ngOnDestroy(): void {
// note: Here you have to be sure to unsubscribe to the subscribe item!
this.onUserChange.unsubscribe();
}
基于:使用类继承来钩子到Angular 2的组件生命周期
另一种通用方法:
导出抽象类UnsubscribeOnDestroy实现OnDestroy {
protected d$: Subject<any>;
构造函数(){
这一点。d$ = new Subject<void>();
const f = this.ngOnDestroy;
这一点。ngOnDestroy = () => {
f ();
this.d $ . next ();
this.d .complete美元();
};
}
public ngOnDestroy() {
/ /空操作
}
}
并使用:
@ component ({
选择器:“my-comp”,
模板:“
})
导出类RsvpFormSaveComponent扩展UnsubscribeOnDestroy实现OnInit {
构造函数(){
超级();
}
ngOnInit(): void {
Observable.of (bla)
.takeUntil (this.d $)
.subscribe(val => console.log(val));
}
}