Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do http polling in ngrx effect

I have this effect, and I'm trying to use timer to poll for data every x seconds. But I can't figure out how timer is supposed to interact with the data streams. I tried adding another switchMap to the top, but then I couldn't pass the action and payload to the second switchmap. Any ideas?

I looked at this post but my situation is a little different. I'm passing a payload with my action that I need to access, and I'm using ngrx 6.

@Effect()
getData = this.actions$
    .ofType(appActions.GET_PLOT_DATA)
    .pipe(
        switchMap((action$: appActions.GetPlotDataAction) => {
            return this.http.post(
                `http://${this.url}/data`,
                action$.payload.getJson(),
                {responseType: 'json', observe: 'body', headers: this.headers});
        }),
        map((plotData) => {
            return {
                type: appActions.LOAD_DATA_SUCCESS,
                payload: plotData
            }
        }),
        catchError((error) => throwError(error))
    )
like image 493
FussinHussin Avatar asked Jan 02 '23 21:01

FussinHussin


1 Answers

This should work (i have tested it). Please add this top of the switchMap. The key operator here is the mapTo. This operator will map the incoming value of the interval into the payload.

switchMap((action$: appActions.GetPlotDataAction) =>
   interval(5000).pipe(mapTo(action$))
);

Update (hint): If you want to start immediately with the polling and then each {n}ms you can use the startWith operator or the timer observable

switchMap((action$: appActions.GetPlotDataAction) =>
  interval(5000).pipe(startWith(0), mapTo(action$))
);

or

switchMap((action$: appActions.GetPlotDataAction) => 
  timer(0, 1000).pipe(mapTo(action$))
);

Update (15.04.2021):

For example with takeUntil and a Subject you can stop the polling stream at a time, somewhere in the code like this. You can also kill when someone click on something. It is up to you and use case depending.

const kill$ = new Subject();
switchMap((action$: appActions.GetPlotDataAction) => 
  timer(0, 1000).pipe(mapTo(action$), takeUntil(kill$))
);

// killing for example after 60 seconds
setTimeout(() => kill$.next(), 60000);
like image 179
Serkan Sipahi Avatar answered Jan 04 '23 09:01

Serkan Sipahi