ngrx / store subscribe вызывается несколько раз. Лучшее место, чтобы отказаться от подписки?

У меня есть угловой компонент, содержащий всплывающее окно NgModal.

Я подписываюсь на магазин ngrx в компоненте.

NgOnDestroy компонента никогда не вызывается, потому что никогда не вызывается новый маршрут.

Пользователь добавляет новых пользователей через модальное всплывающее окно.

Подписка (выбор) на магазин для состояния «пользователь» никогда не отменяет подписку и вызывается много раз.

Как лучше всего справиться с отказом от подписки на store.select (), когда ngOnDestroy () никогда не вызывается?


person Michael JDI    schedule 24.02.2018    source источник
comment
Разве у вас нет подсказки во всплывающем окне, когда оно закрывается? Чтобы вы могли сохранить подписку в компоненте всплывающих окон, а затем отписаться от нее, когда она закрывается?   -  person alsami    schedule 24.02.2018
comment
Проблема в том, что я отправляю сообщение, когда модальное окно закрывается, чтобы я мог получить ответ об успешной публикации обратно родителю. Я попытаюсь подписаться, когда откроется модальное окно, и отказаться от подписки, когда получу сообщение об успешной публикации.   -  person Michael JDI    schedule 25.02.2018


Ответы (2)


Самый простой способ обойти эту проблему - не subscribe в вашем компоненте, сделайте это в шаблоне через async канал.

Из Angular Docs:

Асинхронный канал подписывается на Observable или Promise и возвращает последнее значение, которое он испустил. Когда выдается новое значение, асинхронный конвейер отмечает компонент, который нужно проверить на наличие изменений. Когда компонент уничтожается, асинхронный канал автоматически отписывается, чтобы избежать потенциальных утечек памяти (выделено мной).

Поскольку вы упомянули, что ngOnDestroy не вызывается, то, скорее всего, компонент сохраняется и скрывается / отображается по мере необходимости, и в этом случае вы просто получите одну подписку.

Вы также можете предотвратить множественные вызовы subscribe в шаблоне, используя шаблон «async as», , как объяснено Девиз Тодда здесь. Обычно, когда возникает необходимость в нескольких async каналах в шаблоне, используйте *ngIf="data$ | async as data" на более высоком элементе и ссылайтесь на решенный data ниже.

person John Neuhaus    schedule 14.11.2018
comment
Я пришел к этому вопросу, имея аналогичную проблему, и, действительно, моя проблема была решена с помощью подсказки, данной Тоддом Мотто, с использованием слова «как данные». В моем конкретном случае я несколько раз использовал асинхронный канал в своем html, и, конечно же, это приводило к нескольким подпискам. Спасибо, Джон. - person Juan; 10.06.2019

Уничтожение подписки внутри ngOnDestroy () полезно, если вы не хотите, чтобы эта подписка вызывалась в разных компонентах.

Однако, если подписка вызывается несколько раз в одном компоненте, вы можете решить эту проблему с помощью операторов RxJs.

yourSelectorname$.pipe(skip(1)).pipe(take(1)).subscribe

or

yourSelectorname$.pipe(take(1)).subscribe

Это зависит от ваших потребностей

person Manas Sahu    schedule 26.09.2020