You need to enable JavaScript to run this app. Angular轮询http.get报错Cannot read property 'get' of undefined
优惠活动
大模型
产品
解决方案
定价
更多

Angular轮询http.get报错Cannot read property 'get' of undefined

问题根因

你遇到的Cannot read 'get' of undefined报错,核心是定时器回调的this上下文丢失:

  • 第一次执行this.getData()是在构造函数内直接调用,this正常指向当前LineService实例,因此可以访问注入的http实例,流程正常。
  • 你直接将this.getData作为回调传递给setInterval,没有固定this指向。当定时器第二次触发执行回调时,严格模式下普通函数的this会指向全局/undefined,此时函数内部的this已经脱离了LineService实例,自然访问不到this.http,触发类型错误。
修复方案

1. 解决this绑定问题

两种适配的实现方式,任选其一即可:

  • 修改定时器的回调为箭头函数,直接绑定当前实例的this:
    将构造函数内的setInterval(this.getData, 5000);替换为:
    setInterval(() => this.getData(), 5000);
    
  • 将getData方法定义为箭头函数形式,在类初始化时就固定绑定当前实例的this,无论后续将该方法传给任何回调都不会丢失上下文:
    将原方法定义getData(): void {替换为:
    getData = (): void => {
    

2. 补充工程优化,避免后续运行异常

  • 实现OnDestroy生命周期钩子,在服务销毁时清除定时器、取消未完成的HTTP订阅,避免内存泄漏
  • 给HTTP流增加错误捕获逻辑,避免单个CSV请求失败导致整个数据流中断
  • 定时器触发前先取消上一次未完成的请求,避免数据请求重叠
  • 针对西门子S7-1500 Web服务器的自签HTTPS证书,需在Angular配置中添加忽略SSL校验的逻辑,否则请求会被浏览器拦截
  • 在@Injectable装饰器中添加providedIn: 'root'配置,确保服务为全局单例,避免多实例导致的定时器重复运行
修正后的核心代码片段
import {BehaviorSubject, combineLatest, Subscription} from 'rxjs';
import {HttpClient} from '@angular/common/http';
import {Injectable, OnDestroy} from '@angular/core';

@Injectable({providedIn: 'root'})
export class LineService implements OnDestroy {
  private timerId: number;
  private dataSubscription: Subscription;
  lineSubject = new BehaviorSubject<RcvData[]>([]);

  constructor(private http: HttpClient) {
    this.getData();
    // 固定this指向的定时器回调
    this.timerId = setInterval(() => this.getData(), 5000);
  }

  getData = (): void => {
    // 取消上一次未完成的订阅,避免请求重叠
    this.dataSubscription?.unsubscribe();

    const csvUrlList = [
      'assets/donnee-l1.csv',
      'assets/donnee-l2.csv',
      'assets/donnee-l3.csv',
      'assets/donnee-l4.csv',
      'assets/donnee-l5.csv',
      'https://192.168.0.2/DataLogs?Path=/DataLogs/MyDataLog7.csv&Action=DOWNLOAD&E=1'
    ];

    this.dataSubscription = combineLatest(
      csvUrlList.map(url => this.http.get(url, {responseType: 'text'}))
    ).subscribe({
      next: (results) => {
        const parsedData = results.map(csvContent => {
          const csvRows = csvContent.split('\n');
          const lastValidRow = csvRows[csvRows.length - 2].split(',');
          return new RcvData(
            parseInt(lastValidRow[0], 10),
            lastValidRow[1], lastValidRow[2], parseInt(lastValidRow[3], 10),
            lastValidRow[4], lastValidRow[5], lastValidRow[6], lastValidRow[7],
            parseInt(lastValidRow[8], 10),
            parseInt(lastValidRow[9], 10),
            parseInt(lastValidRow[10], 10),
            parseInt(lastValidRow[11], 10),
            parseFloat(lastValidRow[12]),
            parseFloat(lastValidRow[13]),
            parseFloat(lastValidRow[14]),
            parseFloat(lastValidRow[15]),
            parseFloat(lastValidRow[16]),
            parseInt(lastValidRow[17], 10)
          )
        });
        this.lineSubject.next(parsedData);
      },
      error: (err) => console.error('CSV数据拉取失败', err)
    });
  }

  ngOnDestroy(): void {
    // 清理资源
    clearInterval(this.timerId);
    this.dataSubscription?.unsubscribe();
  }
}

// 原RcvData类实现无需改动
class RcvData{
  seqNo: number;
  date: string;
  utcTime: string;
  id: number;
  name: string;
  refCharge: string;
  refDecharge: string;
  quantiteEnCours: string;
  quantiteHoraireReel: number;
  quantiteHoraireTheorique: number;
  quantitePosteReel: number;
  quantitePosteTheorique: number;
  trpHeureReel: number;
  trpPosteReel: number;
  trpObjectif: number;
  consoAir: number;
  consoElec: number;
  status: number;

  constructor(
    seqNo: number,
    date: string,
    utcTime: string,
    id: number,
    name: string,
    refCharge: string,
    refDecharge: string,
    quantiteEnCours: string,
    quantiteHoraireReel: number,
    quantiteHoraireTheorique: number,
    quantitePosteReel: number,
    quantitePosteTheorique: number,
    trpHeureReel: number,
    trpPosteReel: number,
    trpObjectif: number,
    consoAir: number,
    consoElec: number,
    status: number)
  {
    this.seqNo = seqNo;
    this.date = date.replace(/ /g, '').replace(/"/g, '');
    this.utcTime = utcTime.replace(/ /g, '').replace(/"/g, '');
    this.id = id;
    this.name = name.replace(/"/g, '');
    this.refCharge = refCharge.replace(/ /g, '').replace(/"/g, '');
    this.refDecharge = refDecharge.replace(/ /g, '').replace(/"/g, '');
    this.quantiteEnCours = quantiteEnCours.replace(/ /g, '').replace(/"/g, '');
    this.quantiteHoraireReel = quantiteHoraireReel;
    this.quantiteHoraireTheorique = quantiteHoraireTheorique;
    this.quantitePosteReel = quantitePosteReel;
    this.quantitePosteTheorique = quantitePosteTheorique;
    this.trpHeureReel = trpHeureReel;
    this.trpPosteReel = trpPosteReel;
    this.trpObjectif = trpObjectif;
    this.consoAir = consoAir;
    this.consoElec = consoElec;
    this.status = status;
  }
}

内容的提问来源于stack exchange,提问作者Anthony TARTARE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.02 03:06:05