我最近学会了避免内存泄漏,我需要在组件中退订。为此,我实现了OnDestroy
,但这在导航时引起了问题。
ERROR错误:未捕获(承诺):TypeError:无法读取未定义的属性“ unsubscribe” TypeError:无法读取未定义的属性“取消订阅”
如果我不取消订阅,导航将成功完成。
我的印象是ngOnDestroy
仅在其他所有内容完成后才会发生,显然不是这种情况。
我显然做错了什么,但是我无法弄清楚在离开页面时如何退订?
export class PropertyFormMapperComponent implements OnInit, OnDestroy {
private _routeSubscription: any;
private _getPropertySubscription: any;
constructor(
private _route: ActivatedRoute,
private _propertyFormFileService: PropertyFormFileService,
private _router: Router
) { }
ngOnInit(): void {
this._routeSubscription = this._route.params.subscribe(params => {
this._id = params['id'];
this._getPropertySubscription = this._propertyService.getProperty(this._id).subscribe(property => {
...do stuff...
});
});
}
ngOnDestroy(): void {
this._routeSubscription.unsubscribe();
this._getPropertySubscription.unsubscribe();
}
private onCreate(event: any): void {
this._propertyService.postProperty(property, 1).subscribe(
response => {
...do stuff...
this._router.navigate(['home']);
},
error => {
...other stuff...
}
);
}
}
答案 0 :(得分:1)
在这里,这应该适合您。我使用concatMap
和投影函数组合了路由参数流和getProperty流。您可以在rxjs文档中阅读有关此内容的更多信息:rxjs concatMap
我还使用takeUntil
,当其他流发出时,它从管道中取消订阅。 rxjs takeUntil
因此,当componentDestroyed$
发出observable时,由于takeUntil
将其作为参数,因此takeUntil
将取消订阅this._route.params
和this._propertyService.getProperty
流。
我还向takeUntil
方法中添加了onCreate
,因为您也在那里订阅了。
takeUntil
是跟踪所有Subuscription
并在ngOnDestroy
中手动取消订阅的替代方法。借助takeUntil
,我们可以实现相同的目的,但不必使预订属性混乱。
您可以更进一步,并拥有所有组件类都继承自->的基类,那么您不必在每个组件中保留componentDestroyed$
并可以跳过ngOnDestroy()
部分也是:
export abstract class BaseComponent implements OnDestroy {
protected componentDestroyed$: Subject<void> = new Subject<void>();
ngOnDestroy() {
this.componentDestroyed$.next();
this.componentDestroyed$.complete();
}
}
您的组件现在将从BaseComponent
继承:
export class PropertyFormMapperComponent extends BaseComponent implements OnInit, OnDestroy
您的固定代码:
import {Subscription} from 'rxjs';
import {tap, map, concatMap, takeUntil} from 'rxjs/operators';
export class PropertyFormMapperComponent implements OnInit, OnDestroy {
componentDestroyed$: Subject<void> = new Subject<void>();
constructor(
private _route: ActivatedRoute,
private _propertyFormFileService: PropertyFormFileService,
private _router: Router
) { }
ngOnInit() {
this._route.params
.pipe(
map(params => params['id']),
tap(id => this._id = id),
concatMap(id => this._propertyService.getProperty(id))
takeUntil(this.componentDestroyed$),
tap(property => {
...do stuff...
... side effects are handled in tap functions
})
)
.subscribe();
}
private onCreate(event) {
this._propertyService.postProperty(property, 1)
.pipe(
takeUntil(this.componentDestroyed$)
)
.subscribe(
response => {
...do stuff...
this._router.navigate(['home']);
},
error => {
...other stuff...
}
);
}
ngOnDestroy() {
this.componentDestroyed$.next();
this.componentDestroyed$.complete();
}
}