如果开发一个前端组件,在这个组件里,要发起一个 websocket 请求。但是这个组件又有可能需要复用。不可能每创建一个组件都发起一个 websocket 请求,所以这个 websocket 请求最好是可以复用。这个方案应该如何设计呢
为了设计一个可以复用的 WebSocket 请求,避免每次创建组件时都重新发起请求,你可以采用单例模式(Singleton Pattern)来管理 WebSocket 连接。以下是一个可能的设计方案:
1. 创建一个 WebSocket 管理器
首先,创建一个 WebSocket 管理器类,该类负责管理 WebSocket 连接的创建和复用。
class WebSocketManager {
private static instance: WebSocketManager;
private socket: WebSocket | null = null;
private url: string;
private constructor(url: string) {
this.url = url;
}
public static getInstance(url: string): WebSocketManager {
if (!WebSocketManager.instance) {
WebSocketManager.instance = new WebSocketManager(url);
}
return WebSocketManager.instance;
}
public connect(): WebSocket {
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
this.socket = new WebSocket(this.url);
this.socket.onopen = () => console.log("WebSocket connected");
this.socket.onclose = () => console.log("WebSocket closed");
this.socket.onerror = error => console.error("WebSocket error", error);
this.socket.onmessage = event =>
console.log("WebSocket message", event.data);
}
return this.socket;
}
}
2. 在组件中使用 WebSocket 管理器
在组件中,通过 WebSocket 管理器来获取 WebSocket 实例。
import { defineComponent, onMounted, onUnmounted } from "vue";
import WebSocketManager from "./WebSocketManager";
export default defineComponent({
name: "WebSocketComponent",
setup() {
const url = "wss://example.com/socket";
const webSocketManager = WebSocketManager.getInstance(url);
let socket: WebSocket | null = null;
onMounted(() => {
socket = webSocketManager.connect();
socket.onmessage = event => {
console.log("Message from server:", event.data);
};
});
onUnmounted(() => {
if (socket) {
socket.close();
}
});
return {};
},
});
3. 处理多个组件的订阅
为了确保多个组件可以订阅 WebSocket 消息,你可以在 WebSocketManager 中添加事件分发逻辑。
import { EventEmitter } from "events";
class WebSocketManager extends EventEmitter {
private static instance: WebSocketManager;
private socket: WebSocket | null = null;
private url: string;
private constructor(url: string) {
super();
this.url = url;
}
public static getInstance(url: string): WebSocketManager {
if (!WebSocketManager.instance) {
WebSocketManager.instance = new WebSocketManager(url);
}
return WebSocketManager.instance;
}
public connect(): WebSocket {
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
this.socket = new WebSocket(this.url);
this.socket.onopen = () => console.log("WebSocket connected");
this.socket.onclose = () => console.log("WebSocket closed");
this.socket.onerror = error => console.error("WebSocket error", error);
this.socket.onmessage = event => this.emit("message", event.data);
}
return this.socket;
}
}
在组件中订阅消息:
import { defineComponent, onMounted, onUnmounted } from "vue";
import WebSocketManager from "./WebSocketManager";
export default defineComponent({
name: "WebSocketComponent",
setup() {
const url = "wss://example.com/socket";
const webSocketManager = WebSocketManager.getInstance(url);
const handleMessage = (message: any) => {
console.log("Message from server:", message);
};
onMounted(() => {
webSocketManager.connect();
webSocketManager.on("message", handleMessage);
});
onUnmounted(() => {
webSocketManager.off("message", handleMessage);
});
return {};
},
});
这种设计确保了 WebSocket 连接可以在多个组件之间复用,并且每个组件都可以订阅 WebSocket 消息。通过使用事件发射器(EventEmitter),消息的分发和订阅变得更加灵活和高效。