Back to overview

Angular polling

Angular

Simple auto polling

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {switchMap, map} from 'rxjs/operators';
import {timer} from 'rxjs';

const REFRESH_INTERVAL = 2000;

export interface Player {
  id: number;
  first_name: string;
  last_name: string;
}

export interface PlayerResponse {
  data: Array<Player>;
}

@Injectable({
  providedIn: 'root',
})
export class PlayerService {
  constructor(private http: HttpClient) {}

  api$ = this.http.get<PlayerResponse>('https://www.balldontlie.io/api/v1/players').pipe(
    map((response) => {
      return response.data;
    }),
  );

  players$ = timer(0, REFRESH_INTERVAL).pipe(
    switchMap(() => {
      return this.api$;
    }),
  );
}

https://codesandbox.io/s/polling-api-call-zplybi?file=/src/app/app.component.html

Auto polling until response matches certain condition

  1. Use expand
// delay 2s, and recursive call, but expand doesn't control the interval to make a new request
timer(2000).pipe(
  switchMap(() =>
    this.http.get<VcdTask>(taskUrl).pipe(
      // make recursive http call until response.result is not null
      expand((res) => {
        return res.result === null
          ? this.http.get<VcdTask>(taskUrl).pipe(catchError(() => of({result: null} as VcdTask)))
          : EMPTY;
      }),
      catchError(() => of({result: null} as VcdTask)),
      takeLast(1), // take the matching not-null result only
    ),
  ),
);
  1. Use internal and takeWhile
return interval(2000).pipe(
  concatMap(() => this.http.get<VcdTask>(taskUrl)),
  takeWhile((res) => res.result === null, true), // true is important!
);
  1. throwError and retry
this.http
  .post(API, postData)
  .pipe(
    delay(2000),
    concatMap((data) => {
      this.saveData(data);
      if (when_certain_condition) {
        return throwError(() => new Error(''));
      } else {
        return of(data);
      }
    }),
    retry(),
  )
  .subscribe();