Делать вызов HTTP-запроса каждые x минут в angular 9

Я пытаюсь создать динамический компонент, который будет принимать URL-адрес API, а intervalPeriod говорит «x» минуту в качестве входных данных и извлекать данные каждые x минут, которые передаются в качестве входных данных.

Вот мой stackblitz, который я пробовал, следуя всем ответам на stackoverflow.

Мне нужно показать данные в первый раз в 0 секунд, и после этого он должен извлекать данные каждые x секунд или минут. Это выглядит правильно или что мне здесь не хватает?

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

person Margerine    schedule 16.02.2021    source источник


Ответы (1)


Есть пара вещей, которые я бы изменил:

  • Используйте новый HttpClient, если вы используете Angular ›= 4.3.1
  • Вы должны отказаться от подписки в ngOnDestroy, чтобы подписка не утекала.
  • Измените интервал на таймер с начальным временем 0, чтобы сразу выполнить первый вызов.
  • Переместите подписку на ngOnInit, иначе подписка будет создана до того, как будет установлен intervalPeriod, что приведет к периоду по умолчанию, равному 0 для интервала.
  • catchError, если вы хотите, чтобы ваш интервал оставался активным в случае сбоя одного вызова.
  • Измените flatMap на switchMap, чтобы иметь максимум один HTTP-вызов, без перекрывающихся вызовов. Если первый вызов не завершился, он будет отменен с помощью switchMap при выполнении второго. Это маловероятно с интервалом в 1 минуту, так что не нужно.
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);
  }
}

Вот обновленный Stackblitz

person Yannick Beauchamp-H    schedule 16.02.2021