一、什么是webscoket
二、创建对象
if ("websocket" in window) {
const resrole = await getuserinfo();
//这里对路径进行了配置,关于.env请看上一篇文章
const wsurl = process.env.vue_app_websocket_api + `usercount/${resrole.user.username}`;
socket = new websocket(wsurl);
//上面两行等价于
socket = new websocket("ws://localhost:8080/websocketserver"); //直接写路径
} else {
notification.error({
title: "错误",
message: "您的浏览器不支持websocket,请更换chrome或者firefox",
});
}
三、处理事件
在上面对象创建成功的基础上,就可以使用该对象的处理事件了,主要分为以下四种:
事件 | 事件监听器 | 描述 |
open | websocket.onopen | 用于指定链接成功后的回调函数 |
message | websocket.onmessage | 用于指定当从服务器接受到信息时的回调函数 |
error | websocket.onerror | 用于指定连接失败后的回调函数 |
close | websocket.onclose | 用于指定链接关闭后的回调函数 |
四、websocket基本已经了解,废话不多说直接上完整代码(我写了个js文件)
import { notification } from "element-ui";
import { gettoken } from "../utils/token";
var socket = null;//实例对象
var lockreconnect = false; //是否真正建立连接
var timeout = 20 * 1000; //20秒一次心跳
var timeoutobj = null; //心跳倒计时
var servertimeoutobj = null; //服务心跳倒计时
var timeoutnum = null; //断开 重连倒计时
const initwebsocket = async () => {
if ("websocket" in window) {
const wsurl = '链接地址';
socket = new websocket(wsurl);
socket.onerror = websocketonerror;
socket.onmessage = websocketonmessage;
socket.onclose = closewebsocket;
socket.onopen = openwebsocket;
} else {
notification.error({
title: "错误",
message: "您的浏览器不支持websocket,请更换chrome或者firefox",
});
}
}
//建立连接
const openwebsocket = (e) => {
start();
}
const start = ()=> {
//开启心跳
timeoutobj && cleartimeout(timeoutobj);
servertimeoutobj && cleartimeout(servertimeoutobj);
timeoutobj = settimeout(function() {
//这里发送一个心跳,后端收到后,返回一个心跳消息
if (socket.readystate == 1) {
//如果连接正常
// socket.send("heartbeat");
} else {
//否则重连
reconnect();
}
servertimeoutobj = settimeout(function() {
//超时关闭
socket.close();
}, timeout);
}, timeout);
}
//重新连接
const reconnect =() => {
if (lockreconnect) {
return;
}
lockreconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
timeoutnum && cleartimeout(timeoutnum);
timeoutnum = settimeout(function() {
//新连接
initwebsocket();
lockreconnect = false;
}, 1000);
}
//重置心跳
const reset =() => {
//清除时间
cleartimeout(timeoutobj);
cleartimeout(servertimeoutobj);
//重启心跳
start();
}
const sendwebsocket =(e) =>{
// socket.send(`我发消息了`);
}
const websocketonerror =(e) => {\
initwebsocket();
reconnect();
}
//服务器返回的数据
const websocketonmessage=(e) => {
//判断是否登录
if (gettoken()) {
//window自定义事件[下面有说明]
window.dispatchevent(
new customevent("onmessagews", {
detail: {
data: json.parse(e?.data),
},
})
);
}
reset();
}
const closewebsocket=(e) => {
reconnect();
}
//断开连接
const close =() => {
//websocket对象也有发送和关闭的两个方法,只需要在自定义方法中分别调用send()和close()即可实现。
socket.close();
}
//具体问题具体分析,把需要用到的方法暴露出去
export default { initwebsocket, sendwebsocket, websocketonmessage, close };
window自定义事件
五、在main.js中挂载到vue原型上
import websocket from './utils/websocket';
vue.prototype.$websocket = websocket;
六、在需要建立连接的组件中这样写
async mounted() {
this.initwebsocket();
},
methods: {
async initwebsocket() {
this.$websocket.initwebsocket();
},
},
七、在需要从服务器获取的数据进行操作的组件中这样写
mounted() {
window.addeventlistener("onmessagews", this.getsocketdata);
},
methods: {
getsocketdata(res) {
this.pievalue = number(res.detail.data.sendinfostr.onlineusercount);
this.usernumvalue = number(res.detail.data.sendinfostr.totalusercount);
},
八、在需要关闭连接的组件(比如退出时需要关闭)中这样写
//退出登录
logout() {
this.$confirm("确定要退出登录吗?", "提示", {
confirmbuttontext: "确定",
cancelbuttontext: "取消",
type: "warning",
})
.then(() => {
this.$message({
type: "success",
message: "退出成功!",
});
this.$websocket.close();
localstorage.removeitem("token");
this.$router.push("/login");
}).catch(() => {
this.$message({
type: "info",
message: "已取消退出",
});
});
},
九、除了按钮可以主动关闭websocket连接以外,直接关闭浏览器窗口也会关闭连接,故此需要一个窗口监听器,来防止连接还没断开就关闭窗口,服务端出现异常。
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接
window.onbeforeunload = function () {
websocket.close();
}
发表评论