Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make http request call every x minute in angular 9

I am trying to create a dynamic component that will take api url and intervalPeriod say 'x' minute as input and fetch data every x minute that is passed as input.

Here is my stackblitz that i tried following all the stackoverflow answers..

I need to show data the very first time at 0 seconds and it has to fetch data after that every x second or minute . Does this look right or what am i missing here?

https://stackblitz.com/edit/angular-wzvwmy?file=src%2Fapp%2Fdata-emitter%2Fdata-emitter.component.ts

import { Component, Input, OnInit, Output } from "@angular/core";
import { interval } from "rxjs";
import { flatMap, map } from "rxjs/operators";
import { Http } from "@angular/http";

@Component({
  selector: "app-data-emitter",
  templateUrl: "./data-emitter.component.html",
  styleUrls: ["./data-emitter.component.css"]
})
export class DataEmitterComponent implements OnInit {
  @Output() data: any;
  @Input() apiUrl: any;
  @Input() intervalPeriod: number;

  minutes: number;

  constructor(private http: Http) {}
  ngOnInit() {
    this.minutes = this.intervalPeriod * 60 * 1000;
  }

  subscribes$ = interval(this.minutes)
    .pipe(flatMap(() => this.getData()))
    //this.getData()
    .subscribe(data => {
      this.data = data;
      console.log(this.data);
    });

  getData() {
    return this.http
      .get(this.apiUrl)
      .pipe(map((response: any) => response.json()));
  }
}
like image 817
Margerine Avatar asked Mar 24 '26 21:03

Margerine


1 Answers

There's a couple things I would change:

  • Use the new HttpClient if you use Angular >= 4.3.1
  • You should unsubscribe in ngOnDestroy to not leak subscription.
  • Change interval to timer with an initial time of 0 to do the first call right away.
  • Move subscribe to ngOnInit, otherwise susbcription is created before intervalPeriod is set and result in the default period of 0 for the interval.
  • catchError if you want your interval to remain active if one call fail.
  • Change flatMap to switchMap to have a single http call at most, no overlapping calls. If the first call didn't finish, it will be cancelled with switchMap when doing the second one. This is unlikely with an interval of 1 minutes so not necessary.
import { Component, Input, OnDestroy,  OnInit, Output } from "@angular/core";
import { HttpClient } from '@angular/common/http';
import { of, Subscription, timer } from "rxjs";
import { catchError, filter, switchMap } from "rxjs/operators";

@Component({
  selector: "app-data-emitter",
  templateUrl: "./data-emitter.component.html",
  styleUrls: ["./data-emitter.component.css"]
})
export class DataEmitterComponent implements OnInit, OnDestroy {
  @Output() data: any;
  @Input() apiUrl: any;
  @Input() intervalPeriod: number;

  minutes: number;
  subscription: Subscription;

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.minutes = this.intervalPeriod * 60 * 1000;

    this.subscription = timer(0, this.minutes)
      .pipe(
        switchMap(() => {
          return this.getData()
            .pipe(catchError(err => {
              // Handle errors
              console.error(err);
              return of(undefined);
            }));
        }),
        filter(data => data !== undefined)
      )
      .subscribe(data => {
        this.data = data;
        console.log(this.data);
      });
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }

  getData() {
    return this.http
      .get(this.apiUrl);
  }
}

Here's an updated Stackblitz

like image 171
Yannick Beauchamp-H Avatar answered Mar 27 '26 12:03

Yannick Beauchamp-H



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!