Angular 9应用处理MQTT消息运行5分钟后页面无响应如何解决?
问题核心根因
你代码中存在两个核心逻辑缺陷直接导致长时间运行卡顿:
- series数组初始化后固定为5个元素,你全程仅修改已有元素的
name/value属性,永远不会触发series.length>50的判断,旧数据清理逻辑完全失效 - 每次收到MQTT消息都全量拷贝
multi数组触发ngx-charts全量重绘,若MQTT推送频率高(比如每秒多次),会持续触发Angular全局变更检测,同时matTable也会伴随每次变更检测全量重绘,运行时间越长性能损耗越严重
优化方案
1. 修复数据更新逻辑,减少不必要的重绘
ngx-charts采用OnPush变更检测策略,仅当数据引用变更时才会重绘,无需每次全量拷贝整个multi数组,仅更新修改后的系列引用即可:
bindView(currentSecond: number, data) { // 原有按秒区间更新series元素的逻辑保持不变 if (currentSecond <= 12) { this.multi[0].series[0].name = 5; this.multi[0].series[0].value += data.rx; this.multi[1].series[0].name = 5; this.multi[1].series[0].value += data.tx; } else if (currentSecond > 12 && currentSecond <= 24) { this.multi[0].series[1].name = 10; this.multi[0].series[1].value += data.rx; this.multi[1].series[1].name = 10; this.multi[1].series[1].value += data.tx; } else if (currentSecond > 24 && currentSecond <= 36) { this.multi[0].series[2].name = 15; this.multi[0].series[2].value += data.rx; this.multi[1].series[2].name = 15; this.multi[1].series[2].value += data.tx; } else if (currentSecond > 36 && currentSecond <= 48) { this.multi[0].series[3].name = 20; this.multi[0].series[3].value += data.rx; this.multi[1].series[3].name = 20; this.multi[1].series[3].value += data.tx; } else if (currentSecond > 48 && currentSecond <= 60) { this.multi[0].series[4].name = 25; this.multi[0].series[4].value += data.rx; this.multi[1].series[4].name = 25; this.multi[1].series[4].value += data.tx; } // 仅更新修改后的series引用,避免全量重绘 this.multi[0] = { ...this.multi[0], series: [...this.multi[0].series] }; this.multi[1] = { ...this.multi[1], series: [...this.multi[1].series] }; this.multi = [...this.multi]; // 若你确实需要累积更多数据点,修改长度判断阈值为适配你业务的数值,比如>10就清理旧数据 // if (this.multi[0].series.length > 10) { // this.multi[0].series.splice(0, 5); // this.multi[1].series.splice(0, 5); // } }
2. 限流MQTT消息处理频率
用RxJS操作符限制消息处理频率,避免高频推送导致频繁重绘,比如设置每秒最多处理1次消息:
import { throttleTime } from 'rxjs/operators'; subscribingToMQTT() { // 先清理已存在的订阅,避免重复订阅 if (this._mqttSubscriber) { this._mqttSubscriber.unsubscribe(); } this._mqttSubscriber = this.mqttService .observe(`myTopic`) .pipe(throttleTime(1000)) // 1000ms即1秒,可根据业务需要调整 .subscribe( (jsonLiveData: IMqttMessage) => { let _data = jsonLiveData.payload.toString(); // 生产环境移除console打印,避免日志累积占用内存 // console.log('Live Data: ', _data); this.JSONLiveData = this.IsJsonString(`[${_data}]`); this.bindTxRxData(this.JSONLiveData[0]); }, (error) => { console.log('Something went wrong while fetching live data from MQTT'); } ); }
3. 优化Angular变更检测
给当前组件添加OnPush变更检测策略,减少不必要的全局变更检测触发:
import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ selector: 'your-component-selector', templateUrl: './your-component.component.html', styleUrls: ['./your-component.component.css'], changeDetection: ChangeDetectionStrategy.OnPush // 新增这行 })
同时给matTable添加trackBy函数,避免每次数据变更全量重绘所有表格行:
<!-- matTable 增加trackBy配置 --> <table mat-table [dataSource]="dataSource" [trackBy]="trackByIndex"> <!-- 列定义保持不变 --> </table>
// component.ts 新增trackBy方法 trackByIndex(index: number) { return index; }
如果matTable的数据是持续累积的,也要添加长度限制,比如仅保留最近100条记录,超过则删除最旧的条目,避免表格行数无限增长。
4. 优化ngx-charts渲染配置
关闭不必要的动画,减少渲染开销:
<ngx-charts-line-chart [scheme]="colorScheme" [legend]="legend"[results]="multi" [gradient]="gradient" [xAxis]="showXAxis" [yAxis]="showYAxis" [legend]="showLegend" [legendTitle]="title" [showXAxisLabel]="showXAxisLabel" [showYAxisLabel]="showYAxisLabel" [xAxisLabel]="xAxisLabel" [yAxisLabel]="yAxisLabel" [autoScale]="autoScale" [animations]="false"> <!-- 关闭动画 --> </ngx-charts-line-chart>
内容的提问来源于stack exchange,提问作者naksh
相关产品推荐
相关产品推荐

