angular中websocket前后帧数据对比

angular websocket前后帧数据对比,性能优化

上篇链接: angular中websocket服务消息订阅

主要解决websocket数据量比较大,且需要一次性展示时,导致页面卡顿问题
实现思路为

  • 记录 当前websocket返回数据上一次websocket数据,已经最终处理的数据
  • 将两次数据进行比对,拿到 相同的数据
  • 再将相同的数据对比上一次数据,找出 减少的数据,
  • 将最新数据对比相同数据,找出新增的数据
  • 如果是新增的就直接将它 push到最终处理的数据 中,
  • 然后通过 lodashpullAllWith() 方法,将减少的数据最终数据中移除,
  • 最后用相同的数据的值去更新最终数据的值。避免每次都将整个数据重新绘制。
第一步:引入ChangeDetectorRef模块
import { ChangeDetectorRef} from '@angular/core';
第二步:声明ChangeDetectorRef模块
constructor(private cd: ChangeDetectorRef){}
第三步:引用
在数据修改后调用,从而实现实时检测页面及其子元素的变化(根据我的实际情况)
this.cd.detectChanges();

引入lodash插件
import _ from 'lodash';
————————————————————————————————————————————————————————————————————————————————

	// currentFrameData 	websocket每次最新数据
	// this.preFrameData 	记录上一次数据
	// this.lineOfTrains	处理后展示数据
	
  // 为了提高svg的性能,svg不需要每一帧数据都重新销毁列车然后创建,而是只需更新相同的, 删除减少的,添加新增的。
  comparePreFrameDataWithCurrentFrameData(currentFrameData: SvgTrain[]) {
    // 前后相同的
    const sameTrains = _.intersectionWith(
      currentFrameData,
      this.preFrameData,
      (value: SvgTrain, othValue: SvgTrain) => {
        return value.trainNo === othValue.trainNo;
      },
    );
    // 减少的
    const deleteTrains = _.xorWith(sameTrains, this.preFrameData, (value: SvgTrain, othValue: SvgTrain) => {
      return value.trainNo === othValue.trainNo;
    });
    // 新增的
    const addTrains = _.xorWith(currentFrameData, sameTrains, (value: SvgTrain, othValue: SvgTrain) => {
      return value.trainNo === othValue.trainNo;
    });

    this.addTrains(addTrains);
    this.removeTrains(deleteTrains);
    this.updateTrains(sameTrains);
    // 保存当前帧数据
    this.preFrameData = this.lineOfTrains;
    this.cdr.markForCheck();		// 在数据修改后调用,从而实现实时检测页面及其子元素的变化
  }

  // 添加列车
  addTrains(trains: SvgTrain[]) {
    this.lineOfTrains.push(...trains);
  }

  // 删除列车
  removeTrains(trains: SvgTrain[]) {
    _.pullAllWith(this.lineOfTrains, trains, (value: SvgTrain, othValue: SvgTrain) => {
      return value.trainNo === othValue.trainNo;
    });
  }
  
  // 更新列车
  updateTrains(trains: SvgTrain[]) {
    // 用当前帧数据更新上一帧数据。
    this.updateTrains(this.lineOfTrains, trains);
    // 更新列车详情弹框位置。
    // this.updatePopoverLocation();
  }

  /**
   * 将新数组中的对象属性更新至老数组中的对象,目的是为了减少svg的创建和销毁动作,提高性能。
   */
  updateTrains(orgTrains: SvgTrain[], newTrains: SvgTrain[]) {
    newTrains.forEach((newTrain: SvgTrain) => {
      const orgTrain: SvgTrain = _.find(orgTrains, (item: SvgTrain) => {
        return item.trainNo === newTrain.trainNo;
      });
      // 这5个属性决定了列车在svg上的位置和列车颜色,所以其中任意一个不相等,都重新开始计算x,y值和列车颜色
      if (
        orgTrain.nextstation !== newTrain.nextstation ||
        orgTrain.stopStationId !== newTrain.stopStationId ||
        orgTrain.currentstation !== newTrain.currentstation
      ) {
        // 清除缓存,触发重新计算
        orgTrain.clearCache();
      }
      _.forEach(newTrain, (value, key) => {
        orgTrain[key] = value;
      });
    });
  }
export class SvgTrain {
	lineNo: string; // 所属线路号
  	trainType: string; // 车型
  	trainNo: string; // 车号
  	healthStatus: string; // 健康状态
  	currentstation: number; // 当前站id
  	trainstate: SvgTrainState; // 车辆模式
  	whstate: string; // 运营状态 '1' 在途, '2'入库不稳定, '3'入库稳定, '-1'没有车的位置
	stopStationId: number; // 停靠的站点
	nextstation: number; // 下一站id
	currentstation: number; // 当前站id
	
	private _x: number;
	private _y: number;
  	private _preStationName: string; 		// 上一站的站名
  	private _currentStationName: string;	// 当前站的站名
  	private _nextStationName: string;		// 下一站的站名
	private _trainColor: string;	// 列车图标颜色
  	// 用于清除已缓存的数据
 	clearCache() {
	    this._x = undefined;
	    this._y = undefined;
	    this._preStationName = undefined;
	    this._currentStationName = undefined;
	    this._nextStationName = undefined;
	    this._trainColor = undefined;
  	}
}

Angular *ngFor中使用trackBy提升性能

如果集合 lineOfTrains 数据发生改变,angular不知道如何跟踪集合里面的每一项,就删除了全部的项然后再重新赋值。这样就进行了大量的DOM操作,体验很不好。我们使用TrackBy来跟踪集合里面的每一项,页面就只重绘新增和修改的项,大大提升页面性能。

HTML
<ul>
 <li *ngFor="let item of lineOfTrains; trackBy:trackByItem">{{item.lineNo}}<li>
<ul>
ts
interface Item{
 id:number;
 lineNo: string; // 所属线路号
 trainType: string; // 车型
 trainNo: string; // 车号
 healthStatus: string; // 健康状态
 currentstation: number; // 当前站id
 trainstate: SvgTrainState; // 车辆模式
 whstate: string; // 运营状态 '1' 在途, '2'入库不稳定, '3'入库稳定, '-1'没有车的位置
 stopStationId: number; // 停靠的站点
 nextstation: number; // 下一站id
 currentstation: number; // 当前站id
}

//跟踪(保证唯一性)
trackByItem = (index: number, item: Item) => item.id;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值