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个订阅,您只需在每次使用订阅时推送即可。

这是最简单易行的方法。