angular2 在视图销毁时销毁订阅
angular2 destroying subscriptions on view destroy
我有一个 "appService" 用于处理所有组件(表单、导航等)之间的交互。
我的服务有许多组件订阅的事件发射器(显示结果、选择元素、发布表单等)。
显示新视图时,它会订阅它需要的 appService 事件。现在的问题是当我导航到另一个视图(表单)时,不再需要的视图被销毁,但它的订阅仍然被调用......!我发现引用所有订阅并明确取消订阅一个简单任务的大量样板。我究竟做错了什么?如何简化这个?
示例代码:
export class VendorsForm {
constructor(private appService: AppServiceMain)
{
this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {
//detailed view of this item
this.model = selectedEntity;
this.appService.setFormIsShowingDetail();
})
});
}
}
现在在另一个组件中:
export class CustomersForm {
constructor(private appService: AppServiceMain)
{
this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {
//detailed view of this item
this.model = selectedEntity; this.appService.setFormIsShowingDetail();
})
});
}
}
仅供参考,服务和事件调用组件如下:
export class AppServiceMain {
public onSearchResultSelected$: EventEmitter<IEntity>;
setSelectedEntity(ent: IEntity)
{
this.formstate = states.EntitySelected;
this.onSearchResultSelected$.emit(ent);
}
事件调用组件
export class ResultsComponent {
rowDblClick(ev$)
{
this.appService.setSelectedEntity(ev$.data);
}
如果我愿意,我确实知道如何删除这些订阅。问题是我的表单很大而且功能齐全,而且我有大量非标准引用,有没有一种方法可以在视图被破坏时自动停止监听?我发现手动销毁所有这些很容易出错。
如果您命令式订阅,那么也命令式退订
this.someSubscription = this.appService.onSearchResultSelected$.subscribe((selectedEntity) =>
ngOnDestroy() {
this.someSubscription.unsubscribe();
}
另见
您不需要大量订阅。使用 RxJS.Subject and takeUntil 组合像老板一样处理订阅:
import {Subject} from "rxjs/Subject";
@Component(
{
moduleId: __moduleName,
selector: 'my-view',
templateUrl: '../views/view-route.view.html',
}
)
export class ViewRouteComponent implements OnDestroy
{
componentDestroyed$: Subject<boolean> = new Subject();
constructor(protected titleService: TitleService)
{
this.titleService.emitter1$
.takeUntil(this.componentDestroyed$)
.subscribe(
(data: any) =>
{
// ... do something 1
}
);
this.titleService.emitter2$
.takeUntil(this.componentDestroyed$)
.subscribe(
(data: any) =>
{
// ... do something 2
}
);
// ...
this.titleService.emitterN$
.takeUntil(this.componentDestroyed$)
.subscribe(
(data: any) =>
{
// ... do something N
}
);
}
ngOnDestroy()
{
this.componentDestroyed$.next(true);
this.componentDestroyed$.complete();
}
}
我的做法是:
this.subscriptions.push( this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {}));
ngOnDestroy() {
this.subscriptions.forEach((subscription) => {
subscription.unsubscribe();
});
}
您可以使用这种方式处理n个订阅,您只需在每次使用订阅时推送即可。
这是最简单易行的方法。
我有一个 "appService" 用于处理所有组件(表单、导航等)之间的交互。
我的服务有许多组件订阅的事件发射器(显示结果、选择元素、发布表单等)。
显示新视图时,它会订阅它需要的 appService 事件。现在的问题是当我导航到另一个视图(表单)时,不再需要的视图被销毁,但它的订阅仍然被调用......!我发现引用所有订阅并明确取消订阅一个简单任务的大量样板。我究竟做错了什么?如何简化这个?
示例代码:
export class VendorsForm {
constructor(private appService: AppServiceMain)
{
this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {
//detailed view of this item
this.model = selectedEntity;
this.appService.setFormIsShowingDetail();
})
});
}
}
现在在另一个组件中:
export class CustomersForm {
constructor(private appService: AppServiceMain)
{
this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {
//detailed view of this item
this.model = selectedEntity; this.appService.setFormIsShowingDetail();
})
});
}
}
仅供参考,服务和事件调用组件如下:
export class AppServiceMain {
public onSearchResultSelected$: EventEmitter<IEntity>;
setSelectedEntity(ent: IEntity)
{
this.formstate = states.EntitySelected;
this.onSearchResultSelected$.emit(ent);
}
事件调用组件
export class ResultsComponent {
rowDblClick(ev$)
{
this.appService.setSelectedEntity(ev$.data);
}
如果我愿意,我确实知道如何删除这些订阅。问题是我的表单很大而且功能齐全,而且我有大量非标准引用,有没有一种方法可以在视图被破坏时自动停止监听?我发现手动销毁所有这些很容易出错。
如果您命令式订阅,那么也命令式退订
this.someSubscription = this.appService.onSearchResultSelected$.subscribe((selectedEntity) =>
ngOnDestroy() {
this.someSubscription.unsubscribe();
}
另见
您不需要大量订阅。使用 RxJS.Subject and takeUntil 组合像老板一样处理订阅:
import {Subject} from "rxjs/Subject";
@Component(
{
moduleId: __moduleName,
selector: 'my-view',
templateUrl: '../views/view-route.view.html',
}
)
export class ViewRouteComponent implements OnDestroy
{
componentDestroyed$: Subject<boolean> = new Subject();
constructor(protected titleService: TitleService)
{
this.titleService.emitter1$
.takeUntil(this.componentDestroyed$)
.subscribe(
(data: any) =>
{
// ... do something 1
}
);
this.titleService.emitter2$
.takeUntil(this.componentDestroyed$)
.subscribe(
(data: any) =>
{
// ... do something 2
}
);
// ...
this.titleService.emitterN$
.takeUntil(this.componentDestroyed$)
.subscribe(
(data: any) =>
{
// ... do something N
}
);
}
ngOnDestroy()
{
this.componentDestroyed$.next(true);
this.componentDestroyed$.complete();
}
}
我的做法是:
this.subscriptions.push( this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {}));
ngOnDestroy() {
this.subscriptions.forEach((subscription) => {
subscription.unsubscribe();
});
}
您可以使用这种方式处理n个订阅,您只需在每次使用订阅时推送即可。
这是最简单易行的方法。