写过一篇关于websocekt的文章,感觉不太清楚,所以再次记录下实际项目中的使用方法
在Vue中,created钩子函数中就可以初始化websocket
// created钩子函数中初始化websocekt
created() {
this.initWebSocket()
},
在websocekt初始化完成,连接成功之后,向服务器发送请求
initWebSocket() {
// console.log('---------initWebSocket----10-----')
const vm = this
vm.websocket = new WebSocket(process.env.WEBSOCKET_API)
// vm.websocket = new WebSocket('ws://192.168.5.137:****')
vm.websocket.onopen = function() {
console.log('websocket连接成功')
if (vm.topDeptId && vm.topDeptId !== '') {
***发送请求***
vm.subscribeTop(5, vm.topDeptId.substring(2))
vm.subscribeTop(24, vm.topDeptId.substring(2))
vm.subscribeExpend(4, 'online', vm.topDeptId.substring(2))
}
}
vm.websocket.onmessage = function(evt) {
***接收数据***
const obj = JSON.parse(evt.data)
// console.log('['+new Date().getHours()+':'+new Date().getMinutes()+':'+new Date().getSeconds()+'] receive command('+obj.Command+') message:' + JSON.stringify(obj))
console.log('222222222222222222=>' + obj.Command)
接收数据之后在这里做下判断,根据后端返回不同的Command指令,做不同的操作
websocket.onmessage 是websocket接收数据的方法,这里不过是做了不同的判断而已
switch (obj.Command) {
case '15': // 取消订阅,删除在百度地图上渲染的marker图标
vm.continuecycle=true
const vehIds = obj.Body.VehIds // 当前订阅节点下的所有数据 vehIds为id数组
// console.log('['+new Date().getHours()+':'+new Date().getMinutes()+':'+new Date().getSeconds()+'] receive command('+obj.Command+') message:' + vehIds)
for (const idx in vehIds) {
vm.deleteArray(vm.vehicleList, vehIds[idx])
vm.deleteArray(vm.vehicleIdTmpList, vehIds[idx])
delete vm.vehicleTmpObj[vehIds[idx]]
}
vm.continuecycle=false
setTimeout(function() {
for (const idx in vehIds) {
vm.deleteArray(vm.vehicleIdTmpList, vehIds[idx])
vm.deleteArray(vm.vehicleList, vehIds[idx])
delete vm.vehicleTmpObj[vehIds[idx]]
}
// console.log('地图数据置空555555555')
}, 1000)
// debugger
break
case '26': // 订阅->轨迹数据,从返回数据中获取订阅车辆的经纬度,百度地图渲染数据
// console.log('['+new Date().getHours()+':'+new Date().getMinutes()+':'+new Date().getSeconds()+'] receive command('+obj.Command+') message:' + obj.vId)
vm.continuecycle=true
if (vm.vehicleIdTmpList.indexOf(obj.vId) === -1) {
vm.vehicleIdTmpList.push(obj.vId)
}
// console.log('+++vehicleIdTmpList+++' + vm.vehicleIdTmpList)
vm.vehicleTmpObj[obj.vId] = obj
// console.log('+++vehicleTmpObj+++' + JSON.stringify(vm.vehicleTmpObj))
vm.continuecycle=false
break
case '27': // 实时接收已展开过的节点下车辆上下线通知
// console.log('['+new Date().getHours()+':'+new Date().getMinutes()+':'+new Date().getSeconds()+'] receive command('+obj.Command+') message:' + JSON.stringify(obj))
const offlineVeh = obj.Body.Offline
const onlineVeh = obj.Body.Online
offlineVeh.forEach(vid => {
vm.setDataTotree(vm.treeData, vid+'', {online:'0'})
});
onlineVeh.forEach(vid => {
vm.setDataTotree(vm.treeData, vid+'', {online:'1'})
})
break
case '33': // 企业车辆总数,在线数,离线数统计
// console.log('['+new Date().getHours()+':'+new Date().getMinutes()+':'+new Date().getSeconds()+'] receive command('+obj.Command+') message:' + JSON.stringify(obj))
vm.asideObj = obj.Body
vm.treeData[0].onlineVehicle = obj.Body.onlineVehicle
vm.treeData[0].allVehicle = obj.Body.allVehicle
vm.treeData[0].offlineVehicle= obj.Body.allVehicle-obj.Body.onlineVehicle
break
case '32': // 获取企业所有节点车辆在线数
// console.log('['+new Date().getHours()+':'+new Date().getMinutes()+':'+new Date().getSeconds()+'] receive command('+obj.Command+') message:' + JSON.stringify(obj))
const nodeArr = []
const data = obj.Body
for (const key in data) {
if (data.hasOwnProperty(key)) {
const obj1 = { id: key, count: data[key] }
nodeArr.push(obj1)
}
}
//更新下级机构的车辆总数
for (let i = 0; i < nodeArr.length; i++) {
vm.setDataTotree(vm.treeData[0].children, nodeArr[i].id, nodeArr[i].count)
}
if (data) {
vm.deptStatCache = data;
}
break
default:
break
}
}
如果websocekt发生错误,再次进行连接***
vm.websocket.onerror = function() {
console.log('---------onerror--20-------')
vm.initWebSocket()
}
}
下面是不同的发送请求的方法,不同的请求类型,这里拼了一个不同的请求参数,其实这几个方法也是大同小异
subscribeTop(command, deptId) { // 获取企业节点车辆在线数
const data = {
Command: command,
CommandType: 'online',
Token: getToken(),
Body: {
TopDeptId: deptId
}
}
if (this.websocket.readyState === 1) {
this.websocket.send(JSON.stringify(data))
} else {
console.log('websocket信息发送失败')
}
},
subscribeExpend(command, commandType, deptId) { // 实时接收已展开过的节点下车辆上下线通知
const data = {
Command: command,
CommandType: commandType,
Token: getToken(),
Body: {
deptId: deptId
}
}
if (this.websocket.readyState === 1) {
this.websocket.send(JSON.stringify(data))
} else {
console.log('websocket信息发送失败')
}
},
以上两个方法会在websocket初始化后,连接成功之后触发,请求页面渲染需要的数据,
下面的方法会在用户点击树节点复选框时触发,会根据不同的请求参数(判断的当前的状态,勾选或取消勾选)
给服务端发送不同请求,服务端返回不同的数据,做不同的操作。
该方法会在用户点击树节点复选框时触发*******
subscribe(command, isdept, id) { // 发送websocket消息,获取车辆或者机构下车辆经纬度信息
// console.log('-----------subscribe-------command -> ' + command + ' ; isdept -> '+ isdept + ' ; id -> ' + id);
const data = {
Command: command,
CommandType: 'track',
Token: getToken(),
Body: {
isdept: isdept,
id: id,
activeStatus: this.activeStatus === -1 ? null : this.activeStatus
}
}
console.log('ws请求参数:', data)
if (this.websocket.readyState === 1) {
this.websocket.send(JSON.stringify(data))
console.log('请求发送成功+++++++')
} else {
console.log('websocket信息发送失败')
}
},
这里奉上用户点击树节点复选框的方法
getCurrentKey(data, node) { // 获取当前选中节点的key 复选框点击 data数据为当前点击复选框的内容 id等
const id = data.id.substring(2)
this.checkedList = node.checkedKeys
if (this.checkedList.indexOf(data.id) > -1) {
if (data.type === '3') {
this.clickVehId = id
this.subscribe(1, 1, id)
} else {
this.subscribe(1, 0, id)
}
} else {
if (data.type === '3') {
this.clickVehId = id
if (id === this.vehicleInfo.vId + '') {
this.isShowDialog = false
}
this.subscribe(15, 1, id)
this.deleteArray(this.vehicleList, data.id.substring(2))
} else {
this.subscribe(15, 0, id)
const vehicleArray = []
const arr = this.getSelectArr(vehicleArray, this.treeData[0].children, data.id)
for (let i = 0; i < arr.length; i++) {
this.deleteArray(this.vehicleList, arr[i].id.substring(2))
}
}
}
}
还有一个百度地图渲染的方法,该方法在页面挂载完成之后就会调用,另外还有两个方法在 methods 中定义,mounted中调用,为了方便查阅,我将它们放在了一起,如下
mounted() {
getBaseTree() { // 树节点数据获取加载方法
this.deptTreeQuery = { id: '', activeStatus: this.activeStatus==-1?'':this.activeStatus }
getBaseDept(this.deptTreeQuery).then(res => { // 加载机构树顶级节点
if (res.code === 0) {
// console.log(res)
if (this.websocket.readyState === 1) {
this.subscribeTop(24, res.data[0].id.substring(2))
this.subscribeTop(5, res.data[0].id.substring(2))
this.subscribeExpend(4, 'online', res.data[0].id.substring(2))
}
this.topDeptId = res.data[0].id
this.treeData = res.data
// console.log('-----------getBaseDept---------' + JSON.stringify(this.treeData))
this.$set(this.treeData[0], 'allVehicle', res.data.allCount)
this.$set(this.treeData[0], 'onlineVehicle', res.data.onlineVehicle)
this.$set(this.treeData[0], 'offlineVehicle', res.data.allCount-res.data.onlineVehicle)
this.$set(this.treeData[0], 'children', [])
this.treeData[0].children.push({})
} else {
this.$message({ message: res.msg, type: 'error' })
}
})
},
initLocation() { // 获取localStoragesh数据方法
if (window.localStorage) {
const storage = window.localStorage
const address = storage.getItem('userDeptArea')
// console.log(address)
this.mapCenter = address
}
},
setInterval(() => {
this.pushVehToMap() // 百度地图渲染方法,页面挂载完成调用,每0.5秒调用一次
}, 500)
},
// 地图渲染方法
pushVehToMap() {
const vm = this
let pushCount = vm.pushCount
let pcount = 0
let pushLimit = 10
let count = 0
for (const id in vm.vehicleTmpObj) { // 订阅的对象
count++
}
// console.log('count -> ' + count)
if (pushCount >= vm.vehicleIdTmpList.length || count < pushCount) {
vm.pushCount = 0
pushCount = 0
}
// console.log('--2--' + pushCount + '----11----' + vm.vehicleIdTmpList.length)
for (let idx = pushCount; idx < vm.vehicleIdTmpList.length; idx++) {
const id = vm.vehicleIdTmpList[idx]
if (pcount >= pushLimit || count === 0) {
return
}
if (!vm.vehicleTmpObj.hasOwnProperty(id)) {
continue
}
pcount++
vm.pushCount++
const obj = vm.vehicleTmpObj[id]
// console.log('idx -> ' + idx + ' ; id -> ' + id+ this.continuecycle)
if( this.continuecycle){
break
}
if (vm.clickVehId == obj.vId) {
// 地图渲染
vm.mapCenter = {
lng: obj.currInfo.PosData.Longitude,
lat: obj.currInfo.PosData.Latitude
}
vm.zoom = 18
vm.clickVehId = ''
}
if (vm.vehicleList.length === 0) {
vm.vehicleList.push(obj)
} else {
const arr = []
for (let i = 0; i < vm.vehicleList.length; i++) {
arr.push(vm.vehicleList[i].vId)
}
if (arr.indexOf(obj.vId) > -1) {
const j = vm.contains(arr, obj.vId)
vm.vehicleList[j] = obj
} else {
vm.vehicleList.push(obj)
}
if (vm.vehicleId && vm.vehicleId !== '') {
if (vm.vehicleId === obj.vId) {
vm.vehicleInfo = obj
}
}
}
delete this.vehicleTmpObj[id]
}
}
这里有一个localStorag,相关文档可以查看这里。
具体的代码其实可以不用去看,感兴趣的当然也可以研究,主要是websocket的用法,
建立一个websocket连接,连接成功,发送数据,获取数据,连接出错等都是必要的步骤,发送数据时需要判断websocket连接
状态 websocket.readyState,具体概念性的可以查一下文档。
页面样式基本是这样