4.21 echarts-Websocket前端代码的改造-组件使用,发送数据给服务器,并接收数据-运行代码, 发现客户端的数据发不出去给服务器-断开重连机制
一.学习内容
1.1 Websocket前端代码的改造
1.创建 src/utils/socket_service.js 文件,在该文件定义类SocketServie,并定义成单例设计模式
2.定义连接服务器的方法connect,创建WebSocket实例对象
3.监听事件,onopen:连接成功,onclose:连接失败,onmessage:接收数据
4.存储回调函数:registerCallBack(socketType,callBack) { this.callBackMapping[socketType] = callBack}
5.在监听onmessage对接收数据进行处理
-
对服务器发送的数据反编译转化为对象进行存储
-
获取前端发送给服务器,回调函数的唯一标识
-
在callBackMapping对象中通过此标识找到相应的回调函数进行调用,判断回调函数是否存在
-
判断该回调函数传递的行为,由于当服务器找到接收的action是getData时,它服务器会在接收数据对的基础上增加data字段该字段的值接收客户端需要获取的数据
-
拿到对象中存储组件获取数据的回调函数,通过call调用该函数,调用对象为ScoketService实例,并传递参数,为数据服务器传递过来的数据。
6.定义发送数据的方法,将该数据发送给服务器,并编译成字符串进行发送
7.挂载SocketServie对象到vue原型身上
import ScoketService from './utlits/scoket_server'
//连接服务器端
SocketService.Instance().connect()
Vue.prototype.$socket=ScoketService.Instance()
export default class ScoketService {
//单例
static instance = null
//创建一个方法用于生成类的实例对象
static Instance() {
if (!this.instance) {
this.instance = new ScoketService()
}
return this.instance
}
//定义WebSocket实例属性
ws = null
//判断是否连接成功
connected = false
//延时数据
secondary = 0
issuccess = 0
// 用于存储客户端发送组件函数,用于获取数据的函数
callBackMapping = {}
//连接方法
connect() {
//判断浏览器是否支持使用WebSocket
if (!window.WebSocket) {
return console.log('您的浏览器不支持使用WebSocket')
}
//创建WebSocket实例对象
this.ws = new WebSocket('ws://localhost:9998')
//监听连接成功
this.ws.onopen = () => {
this.connected = true
this.issuccess = 0
console.log('服务器连接成功')
}
//1.服务器连接不成功 2.服务器关闭了连接
this.ws.onclose = e => {
this.connected = false
this.issuccess++
setTimeout(() => {
this.connect()
}, 500 * this.issuccess)
console.log('服务器连接失败')
}
//监听接收消息
this.ws.onmessage = msg =>{
console.log('服务器接收到数据', msg.data)
//真正服务器发送过来的原始数据在msg的data字段中
//对服务器发送的数据反编译转化为对象进行存储
const recvData=JSON.parse(msg.data)
//获取前端发送给服务器,回调函数的唯一标识
const socketType = recvData.socketType
//在callBackMapping对象中通过此标识找到相应的回调函数进行调用
//判断回调函数是否存在
if (this.callBackMapping[socketType]) {
//判断改回调函数传递的行为
if (recvData.action === 'getData') {
//由于当服务器找到接收的action是getData时,它服务器会在接收数据对的基础上增加data字段该字段的值接收客户端需要获取的数据
const realData = JSON.parse(recvData.data)
//拿到对象中存储组件获取数据的函数,通过call调用该函数,调用对象为ScoketService实例,并传递数据服务器传递过来的数据
this.callBackMapping[socketType].call(this,realData)
}else if(recvData.action==='fullScreen'){
}else if(recvData.action==='themeChange'){
}
}
}
}
//存储回调函数
registerCallBack(socketType,callBack) {
this.callBackMapping[socketType] = callBack
}
//取消某一个回调函数
unRegisterCallBack(socketType) {
this.callBackMapping[socketType] = null
}
//定义发送数据的方法,将该数据发送给服务器
send(data) {
if (this.connected) {
this.secondary = 0
this.ws.send(JSON.stringify(data))
} else {
this.secondary++
setTimeout(() => {
this.send(data)
}, 500 * this.secondary)
}
}
}
1.2组件使用,发送数据给服务器,并接收数据
1.created 中注册回调函数
created () {
// 当socket来数据的时候, 会调用getData这个函数,参数1:函数的唯一标识,参数2:回调函数
this.$socket.registerCallBack('trendData', this.getData)
}
2.destroyed 中取消注册
destroyed () {
this.$socket.unRegisterCallBack('trendData')
}
3.mounted 中调用$socket中send发送数据
mounted () {
this.initChart()
// this.getData() 先将getData的调用注释起来
this.$socket.send({
action: 'getData',
//回调函数的唯一标识
socketType: 'trendData',
//告诉服务器哪一个图表数据的获取
chartName: 'trend'
})
......
},
4.在getData函数中接收数据,实例对象调用该函数,并传递服务器传递过来的数据
getData(res){
//获取数据进行存储
this.allData = res;
}
1.3 问题:运行代码, 发现客户端的数据发不出去给服务器
分析:因为在刷新界面之后, 客户端和服务端的连接并不会立马连接成功,需要一段时间进行连接,而 在处于连接状态下就调用
send 是发送不成功的。
解决:需要通过定时器进行异步处理,设置一个属性默认为connected=fasle,通过这个属性在发送数据给服务器之前判断是否连接成功,然后隔一段时间,再次调用send函数进行数据的发送。由于每隔相同的时间进行判断是否连接成功,会有点浪费资源。所以可以设置一个属性变量,每发送一次就加1,在定时器延迟的时间为上一次的时间乘与这个变量,这样可以减少发送的次数提高性能。
// 是否已经连接成功
connected = false
sendRetryCount = 0
send (data) {
console.log('发送数据给服务器:')
//
if (this.connected) {
this.sendRetryCount = 0
this.ws.send(JSON.stringify(data))
} else {
setTimeout(() => {
this.sendRetryCount++
this.send(data)
}, 200 * this.sendRetryCount) // 发送数据尝试的次数越大, 则下一次连接的延迟也就越长
}
}
在 onopen 和onclose时设置 connected 的值
connect () {
......
this.ws.onopen = () => {
console.log('WebSocket 连接成功')
this.connected = true
}
this.ws.onclose=e=>{
this.connected=false
................
}
1.4 断开重连机制
问题:如果初始化连接服务端不成功, 或者连接成功了, 后来服务器关闭了, 这两种情况都会触发 onclose 事件,
我们需要在这个事件中,进行重连.
思路:利用定时器进行延迟调用服务器连接机制,并设置重连次数, 重连次数越大, 下一次再发起重连的延时也就越长,提高性能。
connectRetryCount = 0 // 重连次数, 重连次数越大, 下一次再发起重连的延时也就越长
connect () {
this.ws.onopen = () => {
......
this.connectRetryCount = 0 // 连接成功之后, 重置重连次数
}
......
// 1.服务器连接不成功 2.服务器关闭了连接
this.ws.onclose = e => {
console.log('服务器关闭了连接')
setTimeout(() => {
this.connectRetryCount++
this.connect()
}, 200 * this.connectRetryCount)
}
}