Отменить таймер в эффектах ngrx

У меня есть счетчик. Я хочу, чтобы счетчик подождал x секунд, прежде чем он отобразится. Однако, если REQUEST_DEACTIVATE_SPINNER вызывается в то время, когда счетчик ожидает завершения тайм-аута, он должен остановить выполнение действия ACTIVATE_SPINNER. Я бы хотел отменить активный таймер. Это то, что у меня есть до сих пор.

  @Effect() spinnerActive$ = this.actions$
    .ofType(REQUEST_ACTIVATE_SPINNER, REQUEST_DEACTIVATE_SPINNER)
    .switchMap(action => {
      // create a timer and return it active event sent when timer completes
      if (action.type === REQUEST_ACTIVATE_SPINNER) {
        timer$ = Observable.timer(action.payload.delay || 0)
        .switchMap(() =>
          Observable.of({type: ACTIVATE_SPINNER})
        );
      }

      if (action.type === REQUEST_DEACTIVATE_SPINNER) {
        // check to see if a timer is running if it is cancel it
        if (timer$) {
          // cancel the timer
        }
        return Observable.of({type: DEACTIVATE_SPINNER});
      }
    });

Может ли кто-нибудь показать нам, как отменить таймер, который возвращается в Эффект.


person Scott w    schedule 27.06.2017    source источник


Ответы (2)


Вы сможете решить свою проблему с помощью takeUntil оператор.

Вы можете использовать его для завершения наблюдаемого в switchMap для эффекта REQUEST_ACTIVATE_SPINNER при получении действия REQUEST_DEACTIVATE_SPINNER.

Обратите внимание, что теперь есть два эффекта, поскольку эффект REQUEST_DEACTIVATE_SPINNER теперь не зависит от эффекта REQUEST_ACTIVATE_SPINNER:

@Effect() spinnerActive$ = this.actions$
  .ofType(REQUEST_ACTIVATE_SPINNER)
  .switchMap(action => Observable
    .timer(action.payload.delay || 0)
    .takeUntil(this.actions$.ofType(REQUEST_DEACTIVATE_SPINNER))
    .switchMap(() => Observable.of({ type: ACTIVATE_SPINNER })
  );

@Effect() spinnerDeactive$ = this.actions$
  .ofType(REQUEST_DEACTIVATE_SPINNER)
  .switchMap(action => Observable.of({ type: DEACTIVATE_SPINNER }));

Кроме того, некоторые из операторов switchMap не нужны и могут быть заменены на mapTo:

@Effect() spinnerActive$ = this.actions$
  .ofType(REQUEST_ACTIVATE_SPINNER)
  .switchMap(action => Observable
    .timer(action.payload.delay || 0)
    .takeUntil(this.actions$.ofType(REQUEST_DEACTIVATE_SPINNER))
    .mapTo({ type: ACTIVATE_SPINNER })
  );

@Effect() spinnerDeactive$ = this.actions$
  .ofType(REQUEST_DEACTIVATE_SPINNER)
  .mapTo({ type: DEACTIVATE_SPINNER });
person cartant    schedule 28.06.2017
comment
Отличный ответ и выкройка. - person Neurotransmitter; 26.03.2021

Вызовите unsubscribe() по своей подписке (извините, $timer сам Observable), когда вам нужно убить таймер вручную. Он удаляется, когда к нему больше не применяются подписки.

person A. Tim    schedule 27.06.2017
comment
Спасибо, но проблема, с которой я столкнулся, заключается в том, что я делаю именно это (вызывая отмену подписки) с эффектами ngrx. По сути, вы возвращаете наблюдаемое в хранилище, чтобы оно было подписано на него. Понятия не имею, как заставить его отказаться от подписки. - person Scott w; 27.06.2017
comment
Этот ответ не работает с эффектом ngrx. Не стоит подписываться на эффект, NgRx делает это за кулисами. - person mah.cr; 25.11.2017