一个WebSocket的前端封装类
一、概述
实现一个MyWebSocket
的自定义 WebSocket 类,用于建立与服务器的 WebSocket 连接,并提供了一系列方法来处理连接状态、发送和接收消息、自动重连等功能。该类可以方便地在前端项目中实现与服务器的实时通信。
二、实现思路
- 类的构造函数接收 URL 和可选的配置参数,初始化 WebSocket 连接所需的属性,如连接 URL、重连间隔、最大重连次数、日志级别和各种回调函数等。
- 通过
_initWebsocket
方法初始化 WebSocket 连接,设置连接的打开、关闭、错误和消息接收等事件的处理函数。 - 提供了
getStatus
方法用于获取 WebSocket 的连接状态。 then
方法用于设置接收消息时的回调函数。sendMessage
方法用于向服务器发送 JSON 格式的消息,并在发送前自动添加用户信息(如果消息中没有operatingUserId
,则从localStorage
中获取userId
添加到消息中)。- 当连接出现错误或关闭时,启动自动重连机制,尝试在一定时间间隔后重新建立连接。
三、方法解析
constructor
:初始化类的属性,合并默认配置和传入的配置选项,调用_initWebsocket
方法开始建立连接。getStatus
:返回 WebSocket 的当前连接状态,通过readyState
属性判断连接的状态。then
:设置接收消息时的回调函数,该回调函数在_websocketmessage
方法中被调用。sendMessage
:在发送消息前,先检查消息是否为有效的 JSON 对象,如果不是则抛出错误。然后调用_wrapUserInfo
方法添加用户信息,最后将消息转换为 JSON 字符串并通过 WebSocket 发送。_wrapUserInfo
:检查消息中是否存在operatingUserId
,如果不存在则从localStorage
中获取userId
并添加到消息中。_isJSON
:判断一个对象是否为有效的 JSON 对象,通过检查对象的类型和键的数量来判断。_initWebsocket
:尝试建立 WebSocket 连接,设置连接的各种事件处理函数。如果建立连接过程中出现错误,则启动重连机制。_websocketopen
、_websocketerror
、_websocketclose
、_websocketmessage
:分别处理 WebSocket 的打开、错误、关闭和消息接收事件,调用相应的回调函数和日志方法。_startReconnect
:启动重连机制,设置定时器,在一定时间间隔后尝试重新建立连接,直到达到最大重连次数。_logInfo
、_logWarn
、_logError
:根据日志级别打印不同类型的日志信息。
四、注意事项
- 确保在使用该类时,提供正确的 WebSocket 服务器 URL 和有效的配置选项。
- 注意处理可能出现的错误,如消息不是有效的 JSON 对象、获取
token
或userId
失败等情况。 - 在使用自动重连功能时,要考虑到重连次数和时间间隔的合理性,避免过度频繁的重连对服务器造成压力。
- 确保在合适的时机调用
then
方法设置接收消息的回调函数,以便正确处理接收到的消息。 - 注意在发送消息前,确保消息是有效的 JSON 对象,否则会抛出错误。
五、使用示例
this.MyWebSocket = new MyWebSocket("http://ip:port/websocket");
// 接收消息
this.MyWebSocket.then((e) => {
console.log(e);
});
// 发送消息
this.websocket.sendMessage(JSON.stringify({"info": "我正在操作页面..." }));
六、附源码
const _OPERATING_USER_ID = "userId";
/**
* WebSocket Custom Class
*/
class MyWebSocket {
_url = "";
_ws = null;
_then = null;
_options = null;
_reconnectInterval = 2000;
_reconnectTimeoutId = null;
_reconnectAttempts = 0;
_maxReconnectAttempts = 100;
_logLevel = process.env.NODE_ENV === "development" ? "info" : "warning";
_connectedCallback = null;
_disconnectedCallback = null;
_errorCallback = null;
_messageReceivedCallback = null;
/**
* Constructor for MyWebSocket class. Initializes a new WebSocket connection with the provided URL and options.
*
* @param {string} url - The WebSocket server URL.
* @param {Object} [options={}] - Optional configuration options for the WebSocket connection.
* @param {number} [options.reconnectInterval=2000] - The time interval (in milliseconds) between reconnection attempts.
* @param {number} [options.maxReconnectAttempts=100] - The maximum number of reconnection attempts before giving up.
* @param {string} [options.logLevel="info"] - The log level for WebSocket events. Can be "off", "error", "warn", "info", or "debug".
* @param {function} [options.connectedCallback] - A callback function to be executed when the WebSocket connection is established.
* @param {function} [options.disconnectedCallback] - A callback function to be executed when the WebSocket connection is closed.
* @param {function} [options.errorCallback] - A callback function to be executed when an error occurs during the WebSocket connection.
* @param {function} [options.messageReceivedCallback] - A callback function to be executed when a message is received from the WebSocket server.
*/
constructor(url, options = {}) {
this._url = url;
this._options = {
reconnectInterval: this._reconnectInterval,
maxReconnectAttempts: this._maxReconnectAttempts,
logLevel: "info",
...options,
};
this._reconnectInterval = this._options.reconnectInterval;
this._maxReconnectAttempts = this._options.maxReconnectAttempts;
this._logLevel = this._options.logLevel;
this._connectedCallback = this._options.connectedCallback;
this._disconnectedCallback = this._options.disconnectedCallback;
this._errorCallback = this._options.errorCallback;
this._messageReceivedCallback = this._options.messageReceivedCallback;
this._initWebsocket();
}
/**
* Retrieves the readyState of the WebSocket connection.
*
* @returns {number} The readyState of the WebSocket connection.
* The readyState attribute represents the state of the connection:
* - 0: CONNECTING: The connection is not yet open.
* - 1: OPEN: The connection is open and ready to communicate.
* - 2: CLOSING: The connection is in the process of closing.
* - 3: CLOSED: The connection is closed or couldn't be opened.
*/
getStatus() {
return this._ws.readyState;
}
/**
* Sets a callback function to be executed when a message is received from the WebSocket server.
*
* @param {function} callback - The callback function to be executed when a message is received.
* The callback function will receive two parameters:
* - {Object} msg - The parsed JSON message received from the server.
* - {MessageEvent} event - The original MessageEvent object received from the WebSocket.
*
* @returns {void}
*/
then(callback) {
this._then = callback;
}
/**
* Sends a JSON message to the WebSocket server.
*
* @param {Object} message - The JSON message to be sent.
* @throws {Error} Throws an error if the message is not a valid JSON object.
* @returns {void}
*/
sendMessage(message) {
if (!this._isJSON(message)) {
throw new Error(" could not send non JSON message");
}
this._wrapUserInfo(message);
this._ws.send(JSON.stringify(message));
}
/**
* Wraps the user information in the given message object.
* If the message does not contain the operatingUserId, it retrieves the userId from localStorage and adds it to the message.
*
* @param {Object} message - The message object to be sent to the WebSocket server.
* @returns {void} The function modifies the message object in-place.
*
* @example
* const message = {
* type: 'chat',
* content: 'Hello, WebSocket!'
* };
* _wrapUserInfo(message);
* // After execution, message will be:
* // {
* // type: 'chat',
* // content: 'Hello, WebSocket!',
* // operatingUserId: '12345'
* // }
*/
_wrapUserInfo(message) {
if (!(_OPERATING_USER_ID in message)) {
message.operatingUserId = localStorage.getItem("userId");
}
}
_isJSON(obj) {
if (typeof obj !== "object") {
return false;
}
try {
return Object.keys(obj).length > 0 && typeof obj === "object";
} catch (e) {
return false;
}
}
/**
* Initializes a new WebSocket connection with the provided URL.
*
* @private
* @memberof MyWebSocket
* @returns {void}
*
* @throws {Error} Throws an error if there is an issue initializing the WebSocket connection.
*/
_initWebsocket() {
// config.headers["Authorization"] = localStorage.getItem("token");
try {
const token = localStorage.getItem("token");
if (!token) {
this._logError("get token failed.");
}
const url = `${this._url}?Authorization=${token}`;
this._ws = new WebSocket(url);
const that = this;
this._ws.onopen = (e) => {
return this._websocketopen(that, e);
};
this._ws.onclose = (e) => {
return this._websocketclose(that, e);
};
this._ws.onmessage = (e) => {
return this._websocketmessage(that, e);
};
this._ws.onerror = (e) => {
return this._websocketerror(that, e);
};
} catch (error) {
this._logError("Error initializing WebSocket: " + error.message);
this._startReconnect();
}
}
_websocketopen(that) {
that._logInfo("websocket open");
if (typeof that._connectedCallback === "function") {
that._connectedCallback();
}
if (that._reconnectTimeoutId) {
clearInterval(that._reconnectTimeoutId);
that._reconnectTimeoutId = null;
that._reconnectAttempts = 0;
}
}
_websocketerror(that, event) {
that._logError("websocket error: " + event.message);
if (typeof that._errorCallback === "function") {
that._errorCallback(event);
}
that._startReconnect();
}
_websocketclose(that, event) {
that._logWarn("websocket closed: " + event.reason);
if (typeof that._disconnectedCallback === "function") {
that._disconnectedCallback(event);
}
that._startReconnect();
}
/**
* Handles incoming messages from the WebSocket server.
* Parses the received data as JSON and triggers the appropriate callback functions.
*
* @param {MessageEvent} event - The original MessageEvent object received from the WebSocket.
* @private
* @memberof MyWebSocket
* @returns {void}
*/
_websocketmessage(that, event) {
let msg = {};
try {
msg = JSON.parse(event.data);
} catch (e) {
that._logError("websocket message parse error: " + e.message);
}
if (that._then && typeof that._then === "function") {
that._then(msg, event);
}
if (typeof this._messageReceivedCallback === "function") {
that._messageReceivedCallback(msg, event);
}
}
/**
* Initiates the reconnection process to the WebSocket server.
* This function is called when the WebSocket connection is closed or encounters an error.
* It checks if the maximum reconnection attempts have been reached, logs an error message if necessary,
* and starts a timer to attempt reconnection after the specified interval.
*
* @private
* @memberof MyWebSocket
* @returns {void}
*/
_startReconnect() {
if (this._reconnectTimeoutId) {
return;
}
this._reconnectTimeoutId = setInterval(() => {
this._logInfo("Attempting to reconnect... Attempt " + (this._reconnectAttempts + 1));
this._initWebsocket();
this._reconnectAttempts++;
if (this._reconnectAttempts >= this._maxReconnectAttempts) {
this._logError("Max reconnect attempts reached. Giving up.");
clearInterval(this._reconnectTimeoutId);
return;
}
}, this._reconnectInterval);
}
/**
* Logs an informational message to the console based on the log level.
*
* @param {string} message - The informational message to be logged.
* @returns {void}
*
* @private
* @memberof MyWebSocket
*/
_logInfo(message) {
if (this._logLevel === "info" || this._logLevel === "debug") {
console.log(message);
}
}
/**
* Logs a warning message to the console based on the log level.
*
* @param {string} message - The warning message to be logged.
* @returns {void}
*
* @private
* @memberof MyWebSocket
*/
_logWarn(message) {
if (this._logLevel === "warn" || this._logLevel === "info" || this._logLevel === "debug") {
console.warn(message);
}
}
/**
* Logs an error message to the console based on the log level.
*
* @param {string} message - The error message to be logged.
* @returns {void}
*
* @private
* @memberof MyWebSocket
*/
_logError(message) {
if (this._logLevel !== "off") {
console.error(message);
}
}
}
原文地址:https://blog.csdn.net/eqmaster/article/details/142332495
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!