Reputation: 7873
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.
Upvotes: 2
Views: 1143
Reputation: 1960
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.
Upvotes: 6