Platform: NGRX Effects polling

Created on 19 Feb 2019  路  9Comments  路  Source: ngrx/platform

Is there best practices for polling?

Hi, I'm trying to polling backend using effects.
The problem is I want to re-rendere my app only if server response data changed (so I'm trying to avoid unnecessary state update).
Is it possible? As I know every effect must return action, which triggers reducer, which returns new state. So it either updates state or failes.

effects:

@Effect() solutions: Observable<Action> = this.actions.pipe(
ofType(SolutionActionTypes.GetSolutions),
switchMap(() =>
    timer(0, 3000).pipe(
          switchMap((action: any) => {
            return this.http.get<any>(`/url`, {observe: 'response'}).pipe(
                map((res: any) => {
                    if (res.status === 200) {
                        if(//data's changed) {
                            return {type: SolutionActionTypes.SetSolutions, payload: res.body};
                       } else {
                         ???
                      } 
                    })
                );
            })
        )
    )
);

Most helpful comment

Hi, I've recently wrote an article on polling using ngrx effect. If anyone needs help here is the link: https://bbonczek.github.io/jekyll/update/2018/03/01/polling-with-ngrx.html

All 9 comments

In our project we created NoOpAction which is then fired and it's not handled by any reducer.

_Note: Don't forget to add some "stop" action to your code, otherwise you will keep pulling forever. But of course it depends on your project, maybe it's desired functionality._

In our project we created NoOpAction which is then fired and it's not handled by any reducer.

_Note: Don't forget to add some "stop" action to your code, otherwise you will keep pulling forever. But of course it depends on your project, maybe it's desired functionality._

Thanks for answer! That is NoOpAction? Can't find it in docs

You need to create custom one, it's not the part of NgRx.
Something like:

{ type: SomeActionTypes.NoOp }

You need to create custom one, it's not the part of NgRx.
Something like:

{ type: SomeActionTypes.NoOp }

I've tried this way. But after { type: SomeActionTypes.NoOp } comes, my reducer updates state. It's ever

   case SomeActionTypes.NoOp: {
        return {...state};
 }

or
default:
return state;

And then all my client side 'jumpes'

Well, you shouldn't handle this action at all, so it will fall into default case in all reducers.

Hi, I've recently wrote an article on polling using ngrx effect. If anyone needs help here is the link: https://bbonczek.github.io/jekyll/update/2018/03/01/polling-with-ngrx.html

@bbonczek I read your article and have some questions, so can you help answer me ?

  • How and when dispatch continuePolling action?
  • Does your article support ngrx version 6.5 to up?
    Thanks

@dinhlambcs - there is no continuePolling action - there are only StartPolling and StopPolling actions. ContinuePolling$ effect is called on GetSubnetDevicesSucceded/Failed actions. I've pasted a part of an article below:

import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { Effect, Actions, ofType } from '@ngrx/effects';
import { map, switchMap, catchError, takeWhile, delay } from 'rxjs/operators';
import * as SubnetActions from './subnet.actions.ts';
import SubnetEntry from './subnetEntry.model.ts';

@Injectable()
export class SubnetEffects {
  constructor(
    private actions$: Actions<SubnetActions.SubnetActionsUnion>,
    private http: HttpClient
  ) {}

  private isPollingActive = false; // a flag that indicates whether polling is active or not

  // This effect starts polling. There is no other way of initializing polling that calling StartPollingSubnetDevices action.
  @Effect()
  startPolling$ = this.actions$.pipe(
    ofType(SubnetActions.SubnetActionTypes.StartPollingSubnetDevices),
    map(() => this.isPollingActive = false), // switch flag to true
    switchMap(() => {
      return this.http.get<SubnetEntry>('http://localhost:5000/api/subnet').pipe(
        switchMap(entries => new SubnetActions.GetSubnetDevicesSucceded({ entries })),
        catchError(error => of(new SubnetActions.GetSubnetDevicesFailed({ error })))
      ),
    }),
  );

  // This effect stops polling. There is no other way to stop polling that calling Stop PollingSubnetDevices action.
  @Effect()
  stopPolling$ = this.actions$.pipe(
    ofType(SubnetActions.SubnetActionTypes.StopPollingSubnetDevices),
    map(() => this.isPollingActive = false) // switch flag to false
  );

  // this effect repeats only if time since last response is at least 5 seconds.
  @Effect()
  continuePolling$ = this.actions$.pipe(
    ofType(
      SubnetActions.SubnetActionTypes.GetSubnetDevicesSucceded,
      SubnetActions.SubnetActionTypes.GetSubnetDevicesFailed
    ),
    takeWhile(() => this.isPollingActive), // do this only as long as flag is set to true
    switchMap(() => {
      return this.http.get<SubnetEntry>('http://localhost:5000/api/subnet').pipe(
        delay(5000),
        switchMap(entries => new SubnetActions.GetSubnetDevicesSucceded({ entries })),
        catchError(error => of(new SubnetActions.GetSubnetDevicesFailed({ error })))
      );
    })
  );
}

And I am not sure which version of ngrx was used.

@bbonczek: Need I dispatch startPolling action ? I try to dispatch StartPolling action but api only call once time. I'm using rxjs 6.5 with angular 7, ngrx 7

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brandonroberts picture brandonroberts  路  3Comments

oxiumio picture oxiumio  路  3Comments

doender picture doender  路  3Comments

RichardMisiak picture RichardMisiak  路  3Comments

bhaidar picture bhaidar  路  3Comments