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 { 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 [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米可见 })); }

阅读量:349

点赞量:9

问AI
下面的修改: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) => { // 更新实体位置 }); }); } // ... (其他代码)