在角度 9 中每 x 分钟进行一次 http 请求调用

Mar*_*ine 2 rxjs angular angular9

我正在尝试创建一个动态组件,它将采用 api url 和 IntervalPeriod 表示“x”分钟作为输入,并每隔 x 分钟获取作为输入传递的数据。

这是我尝试遵循所有 stackoverflow 答案的 stackblitz。

我需要在 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()));
  }
}
Run Code Online (Sandbox Code Playgroud)

Yan*_*p-H 10

有几件事我会改变:

  • 如果您使用 Angular >= 4.3.1,请使用新的 HttpClient
  • 您应该在 ngOnDestroy 中取消订阅,以免泄漏订阅。
  • 将间隔更改为初始时间为 0 的计时器,以便立即执行第一次调用。
  • 将 subscribe 移至 ngOnInit,否则在设置intervalPeriod 之前创建 subcription,并导致间隔的默认周期为 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);
  }
}
Run Code Online (Sandbox Code Playgroud)

这是更新的 Stackblitz