angular2 уничтожает подписки при просмотре

У меня есть «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);
    }

Я ДЕЙСТВИТЕЛЬНО понимаю, как удалить эти подписки, если захочу. Проблема в том, что мои формы довольно большие и функциональные, и у меня есть множество нестандартных ссылок. Нет ли способа автоматически прекратить прослушивание, когда представление будет уничтожено? Я считаю, что вручную уничтожить все это довольно подвержено ошибкам.


person user5328504    schedule 01.08.2016    source источник
comment
небольшое замечание: мой ResultsComponent и appService всегда живы и имеют единственный экземпляр   -  person user5328504    schedule 01.08.2016
comment
Не могли бы вы пояснить, почему реализация метода ngOnDestroy не работает для вас? Если вы пропустили: OnDestroy   -  person leovrf    schedule 01.08.2016


Ответы (3)


Если подписаться обязательно, то и отписаться обязательно

 this.someSubscription = this.appService.onSearchResultSelected$.subscribe((selectedEntity) =>

ngOnDestroy() {
  this.someSubscription.unsubscribe();
}

См. также как отписаться от нескольких подписчиков в angular 2

person Günter Zöchbauer    schedule 01.08.2016
comment
спасибо, Гюнтер, на самом деле это то, что я делаю прямо сейчас... я получаю дескриптор всех подписок в массиве... но я ненавижу делать это таким образом... я также видел, что есть способ автоматизировать это с асинхронными каналами, но это тоже ужасно... Я чувствую, что angular2 выдвигает самые странные шаблоны повсюду... как ВЫ справляетесь с этим? может быть, этот подход не подходит для управления потоком приложений? - person user5328504; 01.08.2016
comment
Я не вижу проблемы ни в | async, ни в отписке. - person Günter Zöchbauer; 01.08.2016
comment
Я отмечу ваш ответ - просто скажу, что этот синтаксис - CODE SMELL - person user5328504; 03.08.2016

Вам не нужно иметь кучу подписок. Используйте RxJS.Subject и 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();
    }
}
person metamaker    schedule 09.03.2017

как я это делаю:

this.subscriptions.push( this.appService.onSearchResultSelected$.subscribe((selectedEntity) => {}));

ngOnDestroy() {
  this.subscriptions.forEach((subscription) => {
        subscription.unsubscribe();
    });
}

Таким образом вы можете обрабатывать n количество подписок, вам просто нужно нажимать каждый раз, когда вы используете подписку.

Это самый простой и легкий способ выполнения.

person Chintan Thummar    schedule 11.01.2018