在Vue3中使用Websocket可以让我们轻松地实现实时数据传输。为了方便使用,我们可以封装一个好用的Websocket类。
安装依赖
首先我们需要安装 ws
库来处理Websocket连接,使用以下命令进行安装:
npm install ws --save
使用ts+vue3封装组件
javascript
import { onUnmounted } from 'vue';
//设置
interface SocketOptions {
//心跳间隔
heartbeatInterval?: number;
//超时重传
reconnectInterval?: number;
//最大重传次数
maxReconnectAttempts?: number;
}
class Socket {
//路径
url: string;
ws: WebSocket | null = null;
opts: SocketOptions;
//重传次数
reconnectAttempts: number = 0;
listeners: { [key: string]: Function[] } = {};
//心跳间隔
heartbeatInterval: number | null = null;
//构造函数
constructor(url: string, opts: SocketOptions = {}) {
this.url = url;
this.opts = {
//心跳间隔
heartbeatInterval: 30000,
//超时重传
reconnectInterval: 5000,
//最大重传次数
maxReconnectAttempts: 5,
...opts
};
this.init();
}
//初始化
init() {
this.ws = new WebSocket(this.url);
this.ws.onopen = this.onOpen.bind(this);
this.ws.onmessage = this.onMessage.bind(this);
this.ws.onerror = this.onError.bind(this);
this.ws.onclose = this.onClose.bind(this);
}
//打开
onOpen(event: Event) {
console.log('WebSocket opened:', event);
this.reconnectAttempts = 0;
this.startHeartbeat();
this.emit('open', event);
}
//收到的WebSocket消息
onMessage(event: MessageEvent) {
// console.log('WebSocket message received:', event.data);
this.emit('message', event.data);
}
//错误
onError(event: Event) {
console.error('WebSocket error:', event);
this.emit('error', event);
}
//重连逻辑中,在连接失败后自动重新连接
onClose(event: CloseEvent) {
console.log('WebSocket closed:', event);
this.stopHeartbeat();
this.emit('close', event);
//重连逻辑中,在连接失败后自动重新连接,但会限制重连的次数和每次重连之间的间隔时间
if (this.opts.maxReconnectAttempts !== 0 && this.reconnectAttempts < this.opts.maxReconnectAttempts!) {
setTimeout(() => {
// console.log("我有错误了1111111111111111111111111111111111111");
this.reconnectAttempts++;
this.init();
}, this.opts.reconnectInterval);
}
}
//开始心跳检测
startHeartbeat() {
if (!this.opts.heartbeatInterval) return;
this.heartbeatInterval = window.setInterval(() => {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send('ping');
}
}, this.opts.heartbeatInterval);
}
//停止心跳检测
stopHeartbeat() {
if (this.heartbeatInterval) {
clearInterval(this.heartbeatInterval);
this.heartbeatInterval = null;
}
}
//发送消息
send(data: string) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(data);
} else {
console.error('WebSocket is not open. Cannot send:', data);
}
}
//事件监听器注册功能的实现
on(event: string, callback: Function) {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event].push(callback);
}
//从事件监听器中移除
off(event: string) {
if (this.listeners[event]) {
delete this.listeners[event];
}
}
//在事件监听器中触发一个指定的事件
emit(event: string, data: any) {
this.listeners[event]?.forEach(callback => callback(data));
}
}
export function useSocket(url: string, opts?: SocketOptions) {
const socket = new Socket(url, opts);
onUnmounted(() => {
socket.off('open');
socket.off('message');
socket.off('error');
socket.off('close');
socket.ws?.close(); // 关闭WebSocket连接
});
return {
socket,
send: socket.send.bind(socket),
on: socket.on.bind(socket),
off: socket.off.bind(socket)
};
}
使用
javascript
import { useSocket } from "../../utils/websocket";
const { socket, send, on, off } = useSocket(
`ws://192.168.22.32:8000/v1/user/chats`
);
on("close", () => console.log("Socket closed!"));
//webSocket连接上服务器时
on("open", event => {
console.log("webSocket连接上服务器时", event);
});
socket.on("message", data => {
console.log("Received data:", data); })
send(xxxx);