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
相关产品推荐
相关产品推荐

