之前以为websocket复杂,想使用插件来实现,查了一番资料,原生写法就很简单。
项目需求
查询列表,需要实时获取员工上报的数据
代码部分
Table.vue
<script setup lang="ts">
import { ref, onUnmounted } from "vue";
//页面卸载,关闭socket
onUnmounted(() => {
closeWebSocket();
});
//这里后端接口需要用登录的用户id,通过session获取
const userInfo = getSessStorage("userInfo") as { userId: string };
// WebSocket
const ws = ref();
const initWebSocket = () => {
ws.value = new WebSocket(`ws://${location.host}/commonSocket/${userInfo.userId}`);
ws.value.onopen = () => {
console.log("连接成功");
};
//后端设置心跳,会每间隔一定时间,触发一次,根据内容变化处理逻辑
ws.value.onmessage = (e: any) => {
console.log(e, "广播返回的消息");
//后端约定了,如果返回字符串“UPDATE”,就更新表格
if (e.data === "UPDATE") {
//getTable();
}
};
ws.value.onerror = () => {
console.log("连接错误");
//断连后每5秒重连一次
setTimeout(() => {
initWebSocket();
}, 5000);
};
};
initWebSocket();
//关闭链接(在页面销毁时销毁连接)
const closeWebSocket = () => {
ws.value.close();
};
</script>
因为跨域问题,这里使用了vite的proxy代理功能
vite.config.ts
import { defineConfig} from "vite";
import { resolve } from "path";
……
export default defineConfig(({ command }) => {
return {
resolve: {
alias: {
"@": resolve(__dirname, "src")
},
extensions: [".js", ".json", ".ts"],
},
plugins: [
vue(),
],
server: {
host: "0.0.0.0",
port: 3000,
proxy: {
"/commonSocket": {
// target: 'ws://192.168.0.66:60601/',这是后端接口地址
target: 'ws://192.168.0.66:60601/',
changeOrigin: true,
ws: true
},
},
},
};
});
如果代理设置好,连接成功,以上websocket会打印"连接成功"和输出返回。
完!
补充:
项目运行了一段,对websocket有了更多了解:
websocket保持连接,在网络中断时候,不会报错,短时间恢复网络,还会继续连接上,长时间还未知。
解决办法:
加入一个前端检测机制,每次心跳,后端发送当前时间戳,前端接收保存变量里,用定时器间隔检查时间戳,和当前时间做比较,发现时间间隔大于一定,比如10分钟,说明有一段没收到心跳,就认为断连了,重新初始化websocket