WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它提供了双向的实时通信能力。相对于传统的基于 HTTP 的轮询(polling)或者长轮询(long polling)方式,WebSocket 具有更低的延迟和更高的效率,适用于实时性要求较高的场景。
实现效果:
首先,需要在前端建立一个 WebSocket 连接。你可以使用 JavaScript 的 WebSocket 对象。以下是一个基本的连接示例:
// 从后端获取登录token和用户id
import { getInfo } from "@/api/login.js";
import { getToken } from '@/utils/auth'
// websocket地址
let host = document.location.host
// websocket实例
var ws
// 重连定时器实例
var tt
// websocket重连开关
var websocketswitch = false
// websocket对象
var websocket = {
// websocket建立连接
async Init() {
// 判断浏览器是否支持websocket
if (!'WebSocket' in window) {
this.$modal.msgError('您的浏览器不支持WebSocket')
return
}
// 获取用户id
let res = await getInfo()
let userId = res.user.userName
// 创建websocket实例
ws = new WebSocket("ws://" + host + "/websocket/message/" + userId)
// 监听websocket连接
ws.onopen = function () {
// Message({
// type: 'success',
// message: 'websocket连接成功'
// })
}
// 监听websocket连接错误信息
ws.onerror = function (e) {
// Message({
// message: 'websocket传输发生错误',
// type: 'error'
// })
// 打开重连
reconnect()
}
// 监听websocket接受消息
ws.onmessage = function (e) {
//心跳消息不做处理
if (e.data === 'ok') {
return
}
}
ws.onclose = function () {
reconnect()
}
},
disconnectWs() {
if (ws && ws.readyState === WebSocket.OPEN) { // 确保WebSocket连接已建立且处于打开状态
ws.close(); // 断开连接
} else {
}
},
// websocket连接关闭方法
onClose() {
//关闭断开重连机制
websocketswitch = true
ws.close()
},
// websocket发送信息方法
Send(data) {
// 处理发送数据JSON字符串
let msg = JSON.stringify(data)
// 发送消息给后端
ws.send(msg)
},
// 暴露websocket实例
getWebSocket() {
return ws
}
}
// 监听窗口关闭事件,当窗口关闭时-每一个页面关闭都会触发-扩张需求业务
window.onbeforeunload = function () {
}
// 浏览器刷新重新连接
// 刷新页面后需要重连-并且是在登录之后
if (window.performance.navigation.type == 1 && getToken()) {
//刷新后重连
websocket.Init()
}
// 重连方法
function reconnect() {
// 判断是否主动关闭连接
if (websocketswitch) {
return
}
// 重连定时器-每次websocket错误方法onerror触发他都会触发
tt && clearTimeout(tt)
tt = setTimeout(function () {
websocket.Init()
websocketswitch = false
}, 4000)
}
// 暴露对象
export default websocket
<template>
<div class="message_main" @click="openDown" ref="messageBox">
<el-badge :hidden="noticeCount > 0 ? false : true" :value="noticeCount" class="item">
<el-popover v-model="visible" :ref="`popoverNotice`" placement="bottom-end" width="330" trigger="manual"
:popper-options="{
boundariesElement: 'body',//用于控制弹出框的位置和其他选项
removeOnDestroy: true,
}">
<em class="el-icon-bell" slot="reference"></em>
<!-- 头部选项 -->
<el-tabs v-model="activeIndex" class="el-menu-demo" v-if="ifShow">
<el-tab-pane label="消息通知" name="0" :key="activeIndex">
<!-- 消息内容 循环部分 -->
<div class="box">
<div class="notification_text" v-for="(item, index) in noticeData" :key="index"
@click="handleMessage(item)">
<!-- 消息内容 -->
<div class="text">
<p class="text_content">
{{ '任务名称: ' + item.name }}
</p>
<p class="text_content">
{{ '创建时间: ' + item.createTime }}
</p>
</div>
<el-badge :hidden="todo.unreadCount > 0 ? false : true" :value="todo.unreadCount"
class="text_badge"></el-badge>
</div>
</div>
</el-tab-pane>
</el-tabs>
</el-popover>
</el-badge>
</div>
</template>
<script>
import websocket from "@/utils/socket.js";
import {changeStatus } from "@/api/message";
export default {
data() {
return {
activeIndex: "0",
ifShow: true,
todo: [ ],
noticeData: [ ],
noticeCount: null,
visible: false,
queryParams: {
scene: "module-message-list-web",
},
};
},
beforeCreate() {
websocket.Init();//初始化 WebSocket
},
created() {
setTimeout(() => {
this.getWebSocket();
}, 1000);
},
methods: {
getWebSocket() {
let ws = websocket.getWebSocket();
// websocket.getWebSocket()这个是websocket里面方法返回ws对象(websocket.js)
if (ws.readyState === 1) {
websocket.Send(this.queryParams);
}
// 通过ws这个对象获取这个websocket里面后端推消息前端执行的方法onmessage。
// 给他赋给我们自己方法 this.websocketonmessage
// websocketonmessage(e); 就会执行
ws.onmessage = (e) => {
this.noticeCount = JSON.parse(e.data).total;
this.noticeData = JSON.parse(e.data).rows;
};
},
//弹出框显示与隐藏
openDown() {
this.visible = !this.visible;
},
},
};
</script>