FussinHussin
FussinHussin

Reputation: 1814

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))
    )

Upvotes: 5

Views: 7682

Answers (1)

Serkan Sipahi
Serkan Sipahi

Reputation: 691

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

Upvotes: 10

Related Questions