websocket会实时发送大量数据,导致页面卡顿?

websocket会实时发送大量数据时,我目前写的这些代码,会导致页面卡顿,性能优化我不知道怎么下手了,求大佬指教一下, 有偿。谢谢大佬们

let socketInfo = 'xxxx'

let ws = new WebSocket(socketInfo)

let pingInterval = ref(null) // 心跳间隔ID

let viewer = null

let entity = null

let polylineInitialized = false; // 轨迹线是否已初始化的标志

let polylineEntity = null; // 用于存储轨迹线实体

let pointEntity = null;

const bufferLimit = 50; // 缓冲区大小限制,可以根据需求调整

// 从服务器获取用户角色名

const userRole = computed(() => {

return window.localStorage.getItem('roles')

})

const dropdown1 = ref()

// 点击地图获取经纬度

let longitude = ref(null);

let latitude = ref(null);

onMounted(() => {

init() //加载3d地图,

bindUid()//判断是否绑定uid

LocusModel()//3D地图模型

})

// 地图的基础配置

function init() {

viewer = new Cesium.Viewer('cesiumContainer', {

//cesium的查看器的基本属性

baseLayerPicker: false,//配置图层底图的图标

//加载谷歌影像地图,UrlTemplateImageryProvider该接口是加载谷歌地图服务的接口

imageryProvider: new Cesium.ArcGisMapServerImageryProvider({

// url: "https://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer",

url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer' //卫星地图

})

}

// 判断是否绑定uid

function bindUid(params) {

if (window.localStorage.getItem('CardUID') === '') {

return ElMessage({

message: '车辆终端ID未绑定,请点击右上角的“设置”图标进行绑定。',

type: 'warning',

showClose: true

});

} else {

webValue()

}

}

// 加载websocket

function webValue() {

let oldPositionParams = [];//初始化一个变量来存储旧数据

let positionParams = []; // 用于存储所有的位置参数数据

// 初始Websocket

const onOpen = () => {

const data = JSON.stringify({ command: 1, serializeAlgorithm: 1, token: window.localStorage.getItem('token') });

ws.send(data); // 发送JSON字符串

// 设置心跳间隔为5秒

pingInterval.value = window.setInterval(() => {

const pingMessage = JSON.stringify({

command: 2,

serializeAlgorithm: 1

});

ws.send(pingMessage);

}, 5000);

};

// 接收websocket数据

const onMessage = async (event) => {

const data = JSON.parse(event.data);

if (data.data == undefined) {

console.log('未响应');

} else {

processPositionParams(data.data);

updateCarModelPosition(positionParams);// 实时更新车辆移动位置

if (!polylineInitialized) {

initializePolyline(positionParams); // 初始化轨迹线

polylineInitialized = true;// 标记轨迹线已初始化

} else {

updatePolylinePosition(positionParams); // 更新轨迹线位置

}

updateEntityPositions(positionParams); // 更新实体点的位置和标签文本。

}

};

function processPositionParams(data) {

const targetingTypes = {

0x10: 'RTK',

0x11: 'UWB',

0x12: '融合'

};

const newPositionParam = {

TargetingType: targetingTypes[data.type],

UID: data.uid,

Angle: data.angle,

Height: data.height,

longitude: data.longitude,

latitude: data.latitude

};

if (oldPositionParams.length > 0) {

const oldPosition = oldPositionParams[oldPositionParams.length - 1];

if (isNewDataDifferent(newPositionParam, oldPosition)) {

positionParams.push(newPositionParam);

if (positionParams.length > bufferLimit) {

positionParams.shift();

}

}

} else {

positionParams.push(newPositionParam);

}

oldPositionParams.push(newPositionParam);

if (oldPositionParams.length > bufferLimit) {

oldPositionParams.shift();

}

}

function isNewDataDifferent(newData, oldData) {

// 比较各个参数是否不同,如果有任何一个参数不同,就返回 true 表示数据不同

if (

newData.TargetingType !== oldData.TargetingType ||

newData.UID !== oldData.UID ||

newData.Angle !== oldData.Angle ||

newData.Height !== oldData.Height ||

newData.longitude !== oldData.longitude ||

newData.latitude !== oldData.latitude

) {

return true; // 数据不同

}

return false; // 数据相同

}

const onClose = () => {

window.clearInterval(pingInterval.value); // 清除心跳间隔定时器

console.log('Websocket连接关闭');

webValue();

};

const onError = (error) => {

console.log('Websocket连接错误');

ws.close();

window.clearInterval(pingInterval.value); // 清除心跳间隔定时器

webValue();

};

ws.addEventListener('open', onOpen);

ws.addEventListener('message', onMessage);

ws.addEventListener('close', onClose);

ws.addEventListener('error', onError);

}

// 点击按钮是否显示轨迹点和轨迹线

let checkedPoint = ref(true);

let checkedLines = ref(false);

// 保存checkedPoint和checkedLines的值到LocalStorage

function saveCheckedValues() {

localStorage.setItem('checkedPoint', JSON.stringify(checkedPoint.value));

localStorage.setItem('checkedLines', JSON.stringify(checkedLines.value));

}

// 从LocalStorage中获取checkedPoint和checkedLines的值

function loadCheckedValues() {

const storedCheckedPoint = localStorage.getItem('checkedPoint');

const storedCheckedLines = localStorage.getItem('checkedLines');

if (storedCheckedPoint) {

checkedPoint.value = JSON.parse(storedCheckedPoint);

}

if (storedCheckedLines) {

checkedLines.value = JSON.parse(storedCheckedLines);

}

}

// 监听checkedPoint和checkedLines的变化,并保存到LocalStorage

watch([checkedPoint, checkedLines], saveCheckedValues, { deep: true });

// 在页面加载时加载checkedPoint和checkedLines的值

window.addEventListener('load', loadCheckedValues);

// 车辆模型

let carModelData = null;

let shouldFollowCar = false; // 标志位

function updateCarModelPosition(positions) {

if (positions.length === 0) {

return;

}

const latestPosition = positions[positions.length - 1];

const cartesian3 = Cesium.Cartesian3.fromDegrees(latestPosition.longitude, latestPosition.latitude, 0.4);

if (!carModelData) {

createCarModel(cartesian3, latestPosition.Angle);

} else {

carModelData.position = cartesian3;

const headingPitchRoll = new Cesium.HeadingPitchRoll(

Cesium.Math.toRadians(latestPosition.Angle + 90),

Cesium.Math.toRadians(0),

Cesium.Math.toRadians(0)

);

carModelData.orientation = Cesium.Transforms.headingPitchRollQuaternion(cartesian3, headingPitchRoll);

}

}

function createCarModel(cartesian3, angle) {

const headingPitchRoll = new Cesium.HeadingPitchRoll(

Cesium.Math.toRadians(angle + 90),

Cesium.Math.toRadians(0),

Cesium.Math.toRadians(0)

);

const scaleByDistance = new Cesium.NearFarScalar(200, 120, 1200, 0.6);

const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000);

carModelData = viewer.entities.add({

position: cartesian3,

orientation: Cesium.Transforms.headingPitchRollQuaternion(cartesian3, headingPitchRoll),

model: {

uri: "http://127.0.0.1:5501/car/scene.gltf",

scale: 75,

scaleByDistance,

distanceDisplayCondition,

},

id: 'carModel' // 添加id属性

});

}

// 轨迹点 and 标签文字

let positionsArray = [];

let entityList = [];

function updateEntityPositions(positions) {

for (let i = 0; i < positions.length; i++) {

let entityIndex = entityList.length;

const position = positions[i];

// 创建每个实体点的文本标签

const labelText = `终端ID:${position.UID},定位类型:${position.TargetingType}\n经度:${position.longitude},纬度:${position.latitude}\n角度:${position.Angle},高度:${position.Height}`;

if (i < entityList.length) {

// 如果实体点已经存在,只需更新位置和文本

const cartesian3 = Cesium.Cartesian3.fromDegrees(

position.longitude,

position.latitude,

0.02

);

entityList[i].position = cartesian3;

// 更新标签文本

entityList[i].label.text = labelText;

} else {

// 如果实体点不存在,创建一个新的实体点

const cartesian3 = Cesium.Cartesian3.fromDegrees(

position.longitude,

position.latitude,

0.02

);

const pointLabel = new Cesium.Entity({

position: cartesian3,

point: {

pixelSize: 10,

color: Cesium.Color.BLUE,

show: checkedPoint.value,

outlineColor: Cesium.Color.WHITE,

distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 500),

scaleByDistance: new Cesium.NearFarScalar(100, 1, 300, 0.5),

outlineWidth: 1,

},

label: {

text: labelText, // 设置不同的文本

font: '14pt monospace',

show: new Cesium.CallbackProperty(() => {

return entityIndex === entityList.length - 1;

}, false),

style: Cesium.LabelStyle.FILL_AND_OUTLINE,

outlineWidth: 2,

verticalOrigin: Cesium.VerticalOrigin.BOTTOM,

pixelOffset: new Cesium.Cartesian2(0, -9),

scaleByDistance: new Cesium.NearFarScalar(300, 1, 1200, 0.4),

scale: 1,

fillColor: Cesium.Color.WHITE,

outlineColor: Cesium.Color.WHITE,

},

});

entityList.push(pointLabel);

viewer.entities.add(pointLabel);

}

}

// 移除多余的实体点(如果有的话)

if (entityList.length > positions.length) {

for (let i = positions.length; i < entityList.length; i++) {

viewer.entities.remove(entityList[i]);

}

entityList.length = positions.length; // 调整数组的长度

}

}

// 创建新的轨迹线

let polylineGeometry = null;

let geometryInstance = null;

function initializePolyline(positions) {

const positionsArray = positions.flatMap(pos => [pos.longitude, pos.latitude]);

const positionsInCartesian = Cesium.Cartesian3.fromDegreesArray(positionsArray);

polylineGeometry = new Cesium.PolylineGeometry({

positions: positionsInCartesian,

width: 5,

distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 500),

scaleByDistance: new Cesium.NearFarScalar(100, 10, 500, 1),

});

geometryInstance = new Cesium.GeometryInstance({

geometry: polylineGeometry,

attributes: {

color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)

}

});

const primitive = new Cesium.Primitive({

geometryInstances: geometryInstance,

appearance: new Cesium.PolylineMaterialAppearance({

material: Cesium.Material.fromType(Cesium.Material.ColorType)

})

});

viewer.scene.primitives.add(primitive);

}

// 更新轨迹线位置

function updatePolylinePosition(positions) {

if (geometryInstance) {

const positionsArray = positions.flatMap(pos => [pos.longitude, pos.latitude]);

const positionsInCartesian = Cesium.Cartesian3.fromDegreesArray(positionsArray);

polylineGeometry.positions = positionsInCartesian;

geometryInstance.geometry = polylineGeometry;

geometryInstance.show = checkedLines.value;

}

}

// 获取父组件传递的停车场信息的经纬度

let props = defineProps({

cesiumData: Object,

})

// 3D地图模型

function LocusModel() {

let modelMatrix = new Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3.fromDegrees(104.2255077, 30.57514052)); // gltf数据加载位置(自定义)

let heading = Cesium.Math.toRadians(66); // 设置旋转角度

let orientation = Cesium.Matrix4.fromRotationTranslation(

Cesium.Matrix3.fromRotationZ(heading),

Cesium.Cartesian3.ZERO

);

modelMatrix = Cesium.Matrix4.multiply(modelMatrix, orientation, new Cesium.Matrix4());

viewer.scene.primitives.add(

new Cesium.Model.fromGltf({

url: 'http://127.0.0.1:5501/parking/lq_parking_space.gltf', //gltf文件的URL

modelMatrix: modelMatrix,

scale: 1,

maximumSize: 1,

minimumPixelSize: 0.1,

scaleByDistance: new Cesium.NearFarScalar(300, 1, 1200, 0.5), //设置随图缩放距离和比例

distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000), //设置可见距离 10000米可见

}));

}


回答:

下面的修改:1.用Map来存储位置参数,可以更快查到和更新数据。2.在onMessage事件里,用setTimeout来设置下一次心跳,而不用setInterval这个处理。加了一个重连机制,在onClose和onError事件里,如果WebSocket连接关闭或发生错误,会在5秒后重连。用requestAnimationFrame来更新实体位置,这样可以较少页面卡的情况。

整体的结构可以参考一下:

let positionParams = new Map(); // 用Map来存储位置

function webValue() {

let reconnectInterval = null;

const onOpen = () => {

// ... (其他代码)

clearTimeout(reconnectInterval);

};

const onMessage = async (event) => {

// ... (其他代码)

clearTimeout(pingInterval.value);

pingInterval.value = setTimeout(sendHeartbeat, 5000);

};

const onClose = () => {

console.log('Websocket连接关闭');

reconnectInterval = setTimeout(webValue, 5000);

};

const onError = (error) => {

console.log('Websocket连接错误', error);

reconnectInterval = setTimeout(webValue, 5000);

};

// ... (省略其他代码)

}

function processPositionParams(data) {

// ... (其他代码)

const newPositionParam = {

// ... (其他代码)

};

const oldData = positionParams.get(data.uid);

if (!oldData || isNewDataDifferent(newPositionParam, oldData)) {

positionParams.set(data.uid, newPositionParam);

}

}

function isNewDataDifferent(newData, oldData) {

// ... (其他代码)

}

function updateEntityPositions() {

requestAnimationFrame(() => {

positionParams.forEach((position, uid) => {

// 更新实体位置

});

});

}

// ... (其他代码)

以上是 websocket会实时发送大量数据,导致页面卡顿? 的全部内容, 来源链接: utcz.com/p/934889.html

回到顶部