封装 WebSocket
2024年9月20日大约 2 分钟
封装类
class Socket {
websocket: WebSocket | null = null;
params: any;
heartInterval: any = null;
reconnectTimeout: any = null;
lockReconnect: boolean = false;
/**
* 构造函数
* @param {object} params 构造函数参数
*/
constructor(params: any) {
try {
this.params = params;
this.socketInit(params);
} catch (error) {
console.error("错误: 不支持websocket");
}
}
/**
* 初始化socket
* @param {string} url WebSocket服务器将响应的URL
* @param {function} onopen open事件的回调函数
* @param {function} onmessage message事件的回调函数
* @param {function} onerror error事件的回调函数
* @param {function} onclose close事件的回调函数
* @param {boolean} reconnect 是否启用断线重连 默认为false
* @param {number} timer 心跳周期 若为空或0则不启用
*/
socketInit({
url,
onopen,
onmessage,
onerror,
onclose,
reconnect = false,
timer,
}: {
url: string;
onopen: Function;
onmessage: Function;
onerror: Function;
onclose: Function;
reconnect?: boolean;
timer?: number;
}) {
if (url !== undefined) {
// 若不以wss?开头
if (!/^wss?:\/\//.test(url)) {
const { protocol } = location;
// 则自动补上协议头
url = protocol === "http:" ? "ws://" + url : "wss://" + url;
}
try {
this.websocket = new WebSocket(url);
// 用于指定连接成功后的回调函数。
this.websocket.onopen = (e) => {
console.log("连接成功", e);
if (timer > 0) {
this.heartCheck(timer);
}
if (typeof onopen === "function") {
onopen(e);
}
};
// 用于指定当从服务器接受到信息时的回调函数。
this.websocket.onmessage = (e) => {
console.log("接收数据", e.data);
onmessage(e.data);
};
// 用于指定连接关闭后的回调函数。
this.websocket.onclose = (e) => {
console.log("连接关闭", e);
reconnect && this.reconnect();
if (typeof onclose === "function") {
onclose(e);
}
};
// 用于指定连接失败后的回调函数。
this.websocket.onerror = (e) => {
console.log("连接异常", e);
reconnect && this.reconnect();
if (typeof onerror === "function") {
onerror(e);
}
};
} catch (e) {
reconnect && this.reconnect();
}
}
}
// 发送消息
send(message) {
// readyState 1 表示已经链接并且可以通讯
if (!this.websocket || this.websocket.readyState !== 1) {
console.log("请确认websocket是否已经链接并且可以通讯");
return;
}
this.websocket.send(JSON.stringify(message));
}
// 手动关闭socket
close() {
if (this.heartInterval) {
clearInterval(this.heartInterval);
this.heartInterval = null; // 清空引用
}
if (this.reconnectTimeout) {
clearTimeout(this.reconnectTimeout);
this.reconnectTimeout = null; // 清空引用
}
if (!this.websocket) {
console.log("websocket 不可用");
return;
}
this.websocket.close();
}
// 周期性发送ping 保活
heartCheck(timer) {
this.heartInterval = setInterval(() => {
this.send({ type: "ping" });
}, timer);
}
// 断线重连
reconnect() {
if (this.lockReconnect) return;
this.lockReconnect = true;
this.reconnectTimeout && clearTimeout(this.reconnectTimeout);
this.reconnectTimeout = setTimeout(() => {
this.socketInit(this.params);
this.lockReconnect = false;
}, 5000);
}
}
使用
const options = {
url: "ws://127.0.0.1:8100/websocket",
onmessage: (res) => {
// 接收数据后回调
handler(res);
},
// 保活周期 10s
timer: 10000,
// 断线重连
reconnect: true,
};
const socket = new Socket(options);