2

I am using a polling scheme in my Angular application using NgRx.

To simplify things, I have something like the following:

    public stopPolling$ = createEffect(() => this.actions$.pipe(
        ofType(actions.stopPolling),
        tap(_ => this.isPollingActive = false),    
        map(_ => actions.stopPolling())
      ), { dispatch: false });
     
     public continuePolling$ = createEffect(() => this.actions$.pipe(
        ofType(actions.getData),
        tap(_ => this.logger.debug('continue polling')),    
        delay(8000),    
        switchMap(_ => this.pollData())
      ), { dispatch: false });


    private pollData() {
       if (!this.isPollingActive)
         return;
    }

In my "StopPolling" I set a flag, but if it is restarted (ie isPollingActive is et back to true) while I am in the delay(8000), the delay will exit and I will end up with the getData being called multiple times.

So, my question is, is there a way to step the switchMap(_ => this.pollData()) being called after the delay - ie is there someway to "force the delay to exit" before the timeout period?

Almost (if you know C#/.net). like a manualResetEvent.WaitOne(8000) which can be cancelled by calling Set() on the manualResetEvent object.

1 Answer 1

6

You can create an observable that emits after a delay using timer and unsubscribe with takeUntil to exit early:

this.actions$.pipe(
  ofType(actions.getData),
  tap(_ => this.logger.debug('continue polling')),   
  switchMap(_ =>
    timer(8000).pipe(
      takeUntil(this.actions$.pipe(ofType(actions.stopPolling))),
      concatMap(() => this.pollData())
    )
)

This might also allow you to remove the side-effect this.isPollingActive = false and ensure that the control flow remains within the observable.

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.