/**
* 发起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每次重连时,暴露对外的回调函数
*/
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') {
console.log();('您的浏览器不支持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) { // wsObj.OPEN = 1
// console.log('类型',typeof sendHeartBeat);
if( typeof sendHeartBeat == 'string'){
// 若发送基本类型数据作为心跳,如字符串,直接将参数发送给服务端
wsObj.send(sendHeartBeat)
}else{
// 若发送复杂类型数据作为心跳,如对象,则以回调方式暴露出去(得以支持动态数据)
sendHeartBeat();
}
}
// if (wsObj.readyState === wsObj.CLOSED) { // wsObj.CLOSED = 3
// console.log('readyState=3')
// }
}, 500)
}
function onMessage(evt) {
var received_msg = evt && JSON.parse(evt.data);
msgCallback(received_msg);
// 收到服务器信息, 重置服务器心跳
start();
}
function onError() {
console.log('ws_error');
// 断网重连机制
if(!wsDestroy){
reconnect();
}
}
function onOpen() {
console.log("ws_open");
// 连接成功向服务器发送信息,并开启心跳
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) {
console.log('ws_close',wsObj);
// 如果ws连接正常,则清计时器、断开连接
clearTimeout(timeoutObj);
clearTimeout(serverTimeoutObj);
wsObj?.close?.();
}
}
}
在vue中使用,新建一个websocket.vue文件:
<template>
<div style="position: relative" />
</template>
<script>
// import urlConfig from '../network/request'
// import urlConfig from '../urlConfig'
// import vueEvents from "./vueEvent"
export default {
name: 'WebSocketUtil',
props: {
sId: {
type: String,
default: ''
}
},
data() {
return {}
},
mounted() {
this.initWebSocket()
},
destroyed: function() {
// 离开页面生命周期函数
this.websock.close()
},
methods: {
websocketSend(websock, agentData) {
// 加延迟是为了尽量让ws连接状态变为OPEN
setTimeout(() => {
console.log(websock)
console.log(websock.OPEN)
console.log(websock.CLOSED)
// 添加状态判断,当为OPEN时,发送消息
if (websock.readyState === websock.OPEN) {
// websock.OPEN = 1
// 发给后端的数据需要字符串化
websock.send(JSON.stringify(agentData))
}
if (websock.readyState === websock.CLOSED) {
// websock.CLOSED = 3
console.log('websock.readyState=3')
console.log('ws连接异常,请稍候重试')
}
}, 500)
},
initWebSocket: function() {
console.log('AAAAAAAAA')
// WebSocket与普通的请求所用协议有所不同,ws等同于http,wss等同于https
// const wsUrl = urlConfig.webSocketUrl + (this.sId === '' ? '' : ('/' + this.sId))
const wsUrl = 'ws://ip地址/websocket/httpMessage'
console.log('urlw', wsUrl)
// var token = sessionStorage.getItem('token')
if(typeof (WebSocket) === 'undefined'){
return '当前浏览器不支持websocket!!!'
}
this.websock = new WebSocket(wsUrl)
this.websock.onopen = this.webSocketOnopen
this.websock.onerror = this.webSocketOnerror
this.websock.onmessage = this.webSocketOnmessage
this.websock.onclose = this.webSocketOnclose
this.websocketSend(this.websock, 'websock连接成功')
},
webSocketOnopen: function(e) {
console.log('%c' + e.target.url, 'color: red; font-size: 10px')
console.log('WebSocket连接成功')
},
webSocketOnerror: function(e) {
console.log('WebSocket连接发生错误')
},
webSocketOnmessage(e) {
this.sendData(e.data)
console.log(JSON.parse(e.data))
},
webSocketOnclose: function(e) {
console.log(
'%cwebSocket:' + e.target.url + '断开连接...',
'color: red; font-size: 10px'
)
console.log('connection closed (' + e.code + ')')
},
getWebsocket: function() {},
sendData(mes) {
console.log(mes)
// 在父组件中通过@messageData的方式接受事件和参数
this.$emit('messageData', mes)
// vueEvents.$emit('show-td', mes)
}
}
}