创建一个websocket.js(@/utils/websockets)
自定义插件
/**
* 发起websocket请求函数
* @param {object} wsObj - ws对象
* @param {string} type - 操作websocket:销毁close、创建create
* @param {number} timeout - 心跳间隔时长,默认5000ms
* @param sendHeartBeat - 以心跳,内容体区分string、object
* @param {function} msgCallback - 接收到ws数据,对数据进行处理的回调函数
* @param {function} reCallback - ws每次重连时,暴露对外的回调函数
*/
import { Message } from "element-ui";
export function websocketCommand(
wsObj,
type,
timeout = 5000,
sendHeartBeat,
msgCallback,
reCallback
) {
let wsDestroy = type === "close"; // 销毁标志
let lockReconnect = false; // 是否真正建立连接
let timeoutObj = null; // 心跳倒计时
let serverTimeoutObj = null; // 服务器心跳倒计时
let timeoutnum = null; // 断开 重连倒计时
// 若type传入close,则意图销毁websocket
if (type === "close") {
clearTimeout(timeoutObj);
clearTimeout(serverTimeoutObj);
onClose();
}
// 若type传入create,则意图新建websocket,需初始化ws并发送心跳
if (type === "create") {
initWebsocket();
websocketSend();
}
function initWebsocket() {
if (typeof WebSocket === "undefined") {
Message.warning("您的浏览器不支持WebSocket,无法获取数据");
return false;
}
wsObj.onmessage = function (e) {
onMessage(e);
};
wsObj.onopen = function () {
onOpen();
};
wsObj.onerror = function () {
onError();
};
wsObj.onclose = function () {
onClose();
};
}
function websocketSend() {
// 加延迟是为了尽量让ws连接状态变为OPEN
setTimeout(() => {
// 添加状态判断,当为OPEN时,发送消息
if (wsObj.readyState === wsObj.OPEN) {
if (typeof sendHeartBeat == "string") {
// 若发送基本类型数据作为心跳,如字符串,直接将参数发送给服务端
wsObj.send(sendHeartBeat);
} else {
// 若发送复杂类型数据作为心跳,如对象,则以回调方式暴露出去(得以支持动态数据)
sendHeartBeat();
}
}
}, 500);
}
function onMessage(evt) {
try {
var received_msg = evt && JSON.parse(evt.data);
} catch (e) {
// 转换出错,抛出异常
return
}
msgCallback(received_msg);
// 收到服务器信息, 重置服务器心跳
start();
}
function onError() {
// 断网重连机制
if (!wsDestroy) {
reconnect();
}
}
function onOpen() {
// 连接成功向服务器发送信息,并开启心跳
websocketSend();
start();
}
function reconnect() {
// 避免重复建立连接
if (lockReconnect) {
return;
}
lockReconnect = true;
// 没连接上会一直重连,设置延迟避免请求过多
timeoutnum && clearTimeout(timeoutnum);
timeoutnum = setTimeout(function () {
// 重连
// initWebsocket();
// 若重连后有需额外处理的逻辑,通过reCallback()回调暴露出去
reCallback?.();
lockReconnect = false;
}, timeout);
}
function start() {
// 清计时器
timeoutObj && clearTimeout(timeoutObj);
serverTimeoutObj && clearTimeout(serverTimeoutObj);
// 开启心跳
timeoutObj = setTimeout(function () {
if (wsObj.readyState == 1) {
// 如果连接正常,发送心跳(服务端收到后会返回一条消息)
websocketSend();
} else {
// 否则重连
reconnect();
}
// 超时关闭
serverTimeoutObj = setTimeout(function () {
wsObj.close();
}, timeout);
}, timeout);
}
function onClose() {
if (!wsDestroy) {
// 重连机制
reconnect();
} else if (wsObj.readyState == 1) {
// 如果ws连接正常,则清计时器、断开连接
clearTimeout(timeoutObj);
clearTimeout(serverTimeoutObj);
wsObj?.close?.();
}
}
}
接下来进行引用【在vue文件中】:
// 引入websocket
import { websocketCommand } from "@utils/websocket.js";
在vue文件中使用:
created() {
this.createWs();
},
写在methods中:
// ws连接成功,后台返回的ws数据
receiveMsg(data) {
// 收到服务端发送的数据后,需要处理的逻辑
// 根据业务需求进行逻辑处理
...
},
// 建立连接、发起ws请求,以心跳方式,向服务端发送数据
createWs() {
if (this.wsObj) {
websocketCommand(this.wsObj, "close");
this.wsObj = null;
}
this.wsObj = new WebSocket(
process.env.VUE_APP_WEBSOCKET_API +
"/socket/marketData?token=" +
this.token
);
this.loading = true;
// 若为对象类型,以回调方式发送
websocketCommand(
this.wsObj,
"create",
5000,
this.sendHeartBeat,
this.receiveMsg,
this.reconnectWs
);
},
// 断网重连,需要处理的逻辑
reconnectWs() {
if (this.wsObj) {
this.createWs();
// 业务代码 若交易序列不为空 则需要重新发送请求
if (this.queryParams.type != null) {
this.handleCodeChange();
}
}
},
// websocket发送请求
handleCodeChange() {
let sendObj = { sequenceCode: this.queryParams.type };
this.wsObj.send(JSON.stringify(sendObj));
},
// 以回调方式向服务端发送(对象类型的)心跳
sendHeartBeat() {},
// 销毁websocket
destroyed() {
websocketCommand(this.wsObj, "close");
this.wsObj = null;
},
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。