websocket 事件说明
open:连接成功时触发。
message:收到数据时触发。
error:连接失败时触发。
close:连接被关闭时触发。
以下情况下触发close和error:
1、客户端主动关闭websocket时触发close事件。
2、成功连接websocket后服务器断开时触发close事件。
3、成功连接websocket后断开网络,触发close事件。
4、先断网后连接websocket,先触发error事件,再触发close事件。
5、网络通畅的情况下,连接websocket不成功时,先触发error, 再触发close(选定)
综上,各种异常情况下都会触发close, 各种断开重连的操作,最好放在close事件下。
// 封装websocket
export default class CeWebsocketUtil {
constructor (that) {
this.maxReConnectTimes = 10; // 最大连接次数,默认10次
this.reIntervalTime = 30 * 1000; // 重连间隔时间,默认30秒
this.currentComponent = that;
this.websocket = null;
this.reConnectTimes = 0; // 失败后重新连接次数
}
/**
* 初始化Websocket连接
* @param {*} url ws连接url
*/
initWebsocket (url) {
if (!url) return;
this.websocket && this.closeWebsocket();
this.websocket = new WebSocket(url);
this.websocket.onopen = () => this.onOpenFn();
this.websocket.onmessage = e => this.onMessageFn(e);
this.websocket.onerror = () => {
console.log('onerror:连接失败');
};
// 每次报error之后都会调用close,所以连接失败和断开连接的处理都写在close中
this.websocket.onclose = e => {
this.onCloseFn();
};
}
/*
* 连接成功
*/
onOpenFn () {
const NowFormatter = this.formatDateTime();
if (this.reConnectTimes > 0) {
console.info(`ws重连:第【${this.reConnectTimes}】次连接成功!
****${this.websocket.url}****${NowFormatter}`);
} else {
console.info(`ws连接成功****${this.websocket.url}****${NowFormatter}`);
this.reConnectTimes = 0;
}
// 注册onWsOpen方法
this.currentComponent.onWsOpen();
}
/**
* 收到消息
* @param {*} e 消息事件
*/
onMessageFn (e) {
console.info(`ws收到消息****${this.websocket.url}****${e.data}`);
// 注册onWsMessage方法,接收消息
this.currentComponent.onWsMessage(e.data);
}
/**
* 重新连接
*/
reConnect () {
// 先关掉 再连接
this.websocket && this.websocket.close();
const NowFormatter = this.formatDateTime();
this.reConnectTimes += 1;
console.info(`ws重连:正在尝试第【${this.reConnectTimes}】次连接:****${this.websocket.url}****${NowFormatter}`);
if (this.websocket && this.websocket.url) {
this.initWebsocket(this.websocket.url);
}
}
/**
* 关闭连接
*/
closeWebsocket () {
console.info('WEB端主动关闭websocket');
if (this.websocket) {
this.websocket.close();
this.websocket = null;
}
}
// 关闭连接
onCloseFn () {
const NowFormatter = this.formatDateTime();
console.error(`ws断开连接****${NowFormatter}`);
if (this.currentComponent && !this.currentComponent.manualClose && this.websocket && this.websocket.url) {
if (this.reConnectTimes < this.maxReConnectTimes) {
console.error(`ws断开连接,需要${this.reIntervalTime / 1000}秒后重连****${this.websocket.url}****${NowFormatter}`);
setTimeout(() => {
this.websocket && this.websocket.url && this.reConnect();
}, this.reIntervalTime);
} else {
console.error(`ws重连第【${this.reConnectTimes}】次,不再重连`);
}
}
}
/**
* 发送心跳
* @param {*} data
*/
sendData (data) {
if (this.websocket && this.websocket.readyState === 1) {
console.info(`sendData${JSON.stringify(data)}`);
this.websocket.send(JSON.stringify(data));
} else {
console.error('websocket未连接');
}
}
/**
* 格式化new Date() YYYY-MM-DD HH:mm:ss:ms
* @returns
*/
formatDateTime () {
const Now = new Date();
return `${Now.getFullYear()}-${
Now.getMonth() + 1
}-${Now.getDate()} ${Now.getHours()}:${Now.getMinutes()}:${Now.getSeconds()}:${Now.getMilliseconds()}`;
}
}
2、VUE组件中
2.1 引入封装好的websocket
import CeWebsocketUtil from '@common/ce-websocket-util';
export default {
data () {
return {
ws: null,
manualClose: false, // 是否手动关闭ws
}
}
}
2.2、创建连接,初始化数据
this.ws = new CeWebsocketUtil(this);
const URL = `ws://*****`;
this.ws.initWebsocket(URL);
2.3、 websocket 连接成功
onWsOpen () {
console.log('websocket已连接成功');
this.manualClose = false;
},
2.4、发送心跳
this.ws.sendData({ rule: "hello world" });
2.5、 接收websocket数据
onWsMessage (e) {
// TODO: 处理接收的数据
}
2.6、主动关闭websocket
if (this.ws) {
this.manualClose = true;
this.ws.closeWebsocket();
}