Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cancel a timer in an ngrx effects

I have a spinner I want the spinner to wait for x number of seconds before it is shown. However if REQUEST_DEACTIVATE_SPINNER is called during the time the spinner is waiting for the timeout to complete, it should stop the ACTIVATE_SPINNER action from being fired. Aka I would like to cancel the active timer. This is what I have so far.

  @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});
      }
    });

Could some body possibly show we how to cancel a timer that is being returned to an Effect.

like image 776
Scott w Avatar asked Mar 09 '23 18:03

Scott w


1 Answers

You should be able to solve your problem using the takeUntil operator.

You could use it to complete the observable in the switchMap for the REQUEST_ACTIVATE_SPINNER effect when a REQUEST_DEACTIVATE_SPINNER action is received.

Note that there are now two effects, as the REQUEST_DEACTIVATE_SPINNER effect is now independent of the REQUEST_ACTIVATE_SPINNER effect:

@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 }));

Also, the some of the switchMap operators are unnecessary and could be replaced with 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 });
like image 77
cartant Avatar answered Mar 12 '23 03:03

cartant