Эффекты используются для побочных эффектов в NGRX. Они прослушивают действия, преобразуют это действие в побочный эффект, такой как сетевой запрос, запрос веб-сокета, события API браузера и т. Д., И могут или не могут отправлять новое действие из этого.

Класс Effect по умолчанию является одноэлементным, несмотря на то, что он создается на уровне Root или Feature. Он никогда не уничтожается, поэтому все содержащиеся в нем прослушиватели действий будут всегда слушать Store Actions. Есть сценарии, когда мы хотим отменить подписку всех слушателей на действия и через некоторое время подписаться на них снова.

Реальный сценарий

Представим, что у нас есть приложение для покупок. Есть страница корзины, на которой пользователь может увидеть свои товары в корзине. Он может авторизоваться с помощью всплывающего окна входа в систему, и после успешной авторизации мы должны загружать товары в корзину, не обновляя страницу.

Итак, у нас есть LOGIN_USER_SUCCESS действие, которое уведомляет, что пользователь авторизован.

Также у нас есть LOAD_CART действие, которое будет отправлено после авторизации.

И сам классCartEffect, который объединит эти два

(Для простоты мы отправляем только действие, не извлекая данные из Backend API)

Теперь представим, что пользователь перешел на страницу корзины (наш эффект инициализирован), затем перешел на другую страницу и авторизовался там. Поскольку этот эффект уже инициализирован, он все равно будет прослушивать LOGIN_USER_SUCCESS Action и отправлять LOAD_CART действие, даже если это не было нашим намерением. Это очень простая и очевидная ошибка. Как это исправить?

Мы должны сделать следующее

  • Слушайте действие LOGIN_USER_SUCCESS, только когда пользователь находится на странице корзины
  • Отписаться от слушателя всякий раз, когда пользователь покидает страницу

Реализация ngrxOnRunEffects

Мы можем реализовать ngrxOnRunEffects метод класса aeffect. этот метод отвечает, в зависимости от условий, за подписку и отказ от подписки для всех преобразователей эффектов.

Поэтому нам нужно два дополнительных действия

  • CART_PAGE_INITIALIZED
  • CART_PAGE_DESTROYED

Каждый раз, когда будет отправлено действие CART_PAGE_INITIALIZED, мы должны подписаться на наши преобразователи эффектов, а всякий раз, когда будет отправлено CART_PAGE_DESTROYED, мы должны отменить подписку на наши преобразователи эффектов.

Добавим эти действия:

Теперь отправьте их внутрь cart-page.component соответственно:

Теперь все, что нам осталось, это реализовать метод ngrxOnRunEffects:

Мы подписываемся, наши преобразователи эффектов, всякий раз, когда будет отправлено CART_PAGE_INITIALIZED (с использованием оператора exhaustMap), и отписываемся от всех из них всякий раз, когда будет отправлено CART_PAGE_DESTROYED (с помощью оператора takeUntil)