一 websocket的简介
Websocket 是一种在单个 TCP 连接上进行全双工通信的协议。它使得服务器和客户端之间可以实现实时的、双向的数据传输,与传统的 HTTP 请求 - 响应模式不同。传统的 HTTP 通信是单向的,客户端发起请求,服务器响应,然后连接关闭。而 Websocket 允许服务器主动向客户端推送数据,并且在建立连接后可以持续通信。
二 websocket的封装及使用
1、新建websoket.js
import Vue from 'vue';
class websocketObj {
constructor(url) {
// WebSocket连接地址
this.url = url;
// WebSocket实例对象
this.socket = null;
// 心跳定时器
this.heartInterval = null;
// 重连定时器
this.reconnectTimer = null;
// 心跳消息(可根据服务端要求自定义)
this.pingMessage = {
type: 'heartInterval',
content: '心跳检测正常'
};
// 重连次数
this.reconnectCount = 0;
// 最大重连次数
this.maxReconnectCount = 10;
// 重连时间间隔
this.reconnectInterval = 3000;
// 存储消息
this.receiveMessage = {};
}
// 连接WebSocket方法
connect () {
this.socket = new WebSocket(this.url);
this.socket.onopen = this.onOpen.bind(this);
this.socket.onmessage = this.onMessage.bind(this);
this.socket.onclose = this.onClose.bind(this);
this.socket.onerror = this.onError.bind(this);
}
// 连接打开时的回调
onOpen () {
console.log('盼盼测试链接socket,链接正常');
// 开启心跳检测
this.startPing();
}
// 接收到消息时的回调
onMessage (event) {
const message = event.data;
let messageData = null;
try {
messageData = JSON.parse(message);
} catch (error) {
messageData = message;
}
// 判断是否有消息
if (messageData) {
const messageType = messageData.type;
if (this.receiveMessage[messageType]) {
this.receiveMessage[messageType].forEach(callback => {
callback(messageData);
});
}
}
// 收到消息后重置心跳检测
this.resetPing();
}
// 连接关闭时
onClose (event) {
console.log('WebSocket连接已关闭', event);
// 清除心跳定时器
this.clearPing();
// 判断是否需要重连
if (this.reconnectCount < this.maxReconnectCount) {
this.reconnect();
} else {
console.log('已达到最大重连次数,不再尝试重连');
}
}
// 出现错误时的回调
onError (error) {
console.log('WebSocket出现错误:', error);
// 关闭连接,触发onClose方法来进行后续处理(如重连判断等)
this.socket.close();
}
// 发送消息方法
send (message) {
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
this.socket.send(message);
} else {
console.log('WebSocket未连接或连接不可用,无法发送消息');
}
}
// 开启心跳检测
startPing () {
this.heartInterval = setInterval(() => {
this.send(JSON.stringify(this.pingMessage));
}, 5000); // 心跳间隔时间,这里设置为5秒,可按需调整
}
// 重置心跳检测(重新计时)
resetPing () {
clearInterval(this.heartInterval);
this.startPing();
}
// 清除心跳定时器
clearPing () {
clearInterval(this.heartInterval);
}
// 重连方法
reconnect () {
this.reconnectCount++;
console.log(`第${this.reconnectCount}次尝试重连...`);
this.reconnectTimer = setTimeout(() => {
this.connect();
}, this.reconnectInterval);
}
// 接收消息回调
subscribe (messageType, callback) {
console.log(messageType, callback)
if (!this.receiveMessage[messageType]) {
this.receiveMessage[messageType] = [];
}
this.receiveMessage[messageType].push(callback);
}
// 删除消息回调
unsubscribe (messageType, callback) {
if (this.receiveMessage[messageType]) {
const index = this.receiveMessage[messageType].indexOf(callback);
if (index > -1) {
this.receiveMessage[messageType].splice(index, 1);
}
}
}
}
// 创建单例模式的WebSocketManager实例
const webSocketManager = new websocketObj('ws://localhost:8888/websocket/123');
// 导出实例以及Vue的混入方法(用于方便组件使用)
export default {
install (Vue) {
Vue.prototype.$socketApi = webSocketManager;
},
webSocketManager
};
2、main.js 挂载
import WebSocketManager from '@/common/js/websoket.js';
Vue.use(WebSocketManager)
3、vue页面使用
mounted () {
this.$socketApi.connect();// 启动websocket
},
4、vue页面发送消息
methods: {
sendMessage () { //发送消息方法
let a = {
type: '1',
common: '卫盼1'
}
let b = {
type: '2',
common: '卫盼2'
}
let c = {
type: '3',
common: '卫盼3'
}
let d = {
type: '4',
common: '卫盼4'
}
this.$socketApi.send(JSON.stringify(a));
this.$socketApi.send(JSON.stringify(b));
this.$socketApi.send(JSON.stringify(c));
this.$socketApi.send(JSON.stringify(d));
}
},
5、页面消息接收
mounted () {
this.$socketApi.connect();// 启动websocket
this.$socketApi.subscribe('1', (message) => {
this.data.push(message)
});
this.$socketApi.subscribe('2', (message) => {
this.data.push(message)
});
this.$socketApi.subscribe('3', (message) => {
this.data.push(message)
});
this.$socketApi.subscribe('4', (message) => {
this.data.push(message)
});
},
6、当组件销毁时,关闭 WebSocket 连接以及清除重连定时器,避免出现内存泄漏等问题。
beforeDestroy () {
// 组件销毁时,关闭WebSocket连接并清除定时器
if (this.$socketApi.socket) {
this.$socketApi.socket.close();
}
if (this.$socketApi.reconnectTimer) {
clearTimeout(this.$socketApi.reconnectTimer);
}
}