Angular 4 取消订阅导致导航时出错
Angular 4 unsubscribe causes an error when navigating
我最近学会了避免内存泄漏,我需要取消订阅我的组件。为此,我实施了 OnDestroy
但这在导航时引起了问题。
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'unsubscribe' of undefined
TypeError: Cannot read property 'unsubscribe' of undefined
如果我不退订导航成功完成。
我的印象是 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...
}
);
}
}
在这里,这个应该适合你。我使用 concatMap
和投影函数组合了路由参数流和 getProperty 流。您可以在 rxjs 文档中阅读更多相关信息:rxjs concatMap
我还使用 takeUntil
取消订阅其他流发出时通过管道传输到的流。 rxjs takeUntil
因此,当 componentDestroyed$
observable 发出时,因为 takeUntil
将其作为参数,takeUntil
将取消订阅 this._route.params
和 this._propertyService.getProperty
流。
我还添加了 takeUntil
到 onCreate
方法,因为你也在那里订阅。
takeUntil
是跟踪所有 Subuscription
并在 ngOnDestroy
中手动取消订阅的替代方法。使用 takeUntil
我们实现了相同的目的,但不必使用订阅属性使组件混乱。
您可以更进一步,拥有一个基础 class,您的所有组件 class 都继承自 --> 然后您不必保留 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();
}
}
我最近学会了避免内存泄漏,我需要取消订阅我的组件。为此,我实施了 OnDestroy
但这在导航时引起了问题。
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'unsubscribe' of undefined TypeError: Cannot read property 'unsubscribe' of undefined
如果我不退订导航成功完成。
我的印象是 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...
}
);
}
}
在这里,这个应该适合你。我使用 concatMap
和投影函数组合了路由参数流和 getProperty 流。您可以在 rxjs 文档中阅读更多相关信息:rxjs concatMap
我还使用 takeUntil
取消订阅其他流发出时通过管道传输到的流。 rxjs takeUntil
因此,当 componentDestroyed$
observable 发出时,因为 takeUntil
将其作为参数,takeUntil
将取消订阅 this._route.params
和 this._propertyService.getProperty
流。
我还添加了 takeUntil
到 onCreate
方法,因为你也在那里订阅。
takeUntil
是跟踪所有 Subuscription
并在 ngOnDestroy
中手动取消订阅的替代方法。使用 takeUntil
我们实现了相同的目的,但不必使用订阅属性使组件混乱。
您可以更进一步,拥有一个基础 class,您的所有组件 class 都继承自 --> 然后您不必保留 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();
}
}