class SocketPlugin {
opts: {
url: string;
sendMessage: string;
webSocketBack: Function;
pingTimeout: number;
pongTimeout: number;
reconnectTimeout: number;
pingMsg: string;
repeatLimit: number;
};
ws: any;
repeatNum: number;
onclose: Function;
onerror: Function;
onopen: Function;
onmessage: Function;
onreconnect: Function;
lockReconnect: boolean;
forbidReconnect: boolean;
pingTimeoutId;
pongTimeoutId;
constructor(params) {
this.opts = {
url: params.url,
sendMessage: params.sendMessage,
webSocketBack: params.webSocketBack,
pingTimeout: params.pingTimeout || 15000,
pongTimeout: params.pongTimeout || 10000,
reconnectTimeout: params.reconnectTimeout || 2000,
pingMsg: params.pingMsg || "heartbeat",
repeatLimit: params.repeatLimit || 5,
};
this.ws = null; // websocket实例
this.repeatNum = 0;
this.onclose = () => {
console.log("close connect");
};
this.onerror = () => {};
this.onopen = () => {
if (this.opts.sendMessage) {
this.ws.send(this.opts.sendMessage);
}
};
this.onmessage = (event) => {
if (typeof this.opts.webSocketBack === "function") {
if (event) {
this.opts.webSocketBack(event);
}
}
};
this.onreconnect = () => {};
this.createWebSocket();
}
createWebSocket() {
try {
if ("WebSocket" in window) {
this.ws = new WebSocket(this.opts.url);
} else {
alert("当前浏览器不支持websocket协议,建议使用现代浏览器");
}
this.initEventHandle();
} catch (e) {
this.reconnect();
throw e;
}
}
initEventHandle() {
this.ws.onclose = () => {
this.onclose();
this.reconnect();
};
this.ws.onerror = () => {
this.onerror();
this.reconnect();
};
this.ws.onopen = () => {
this.repeatNum = 0;
this.onopen();
// 心跳检测重置
this.heartCheck();
};
this.ws.onmessage = (event) => {
console.log(event);
console.log(this.pongTimeoutId);
// 如果获取到消息,心跳检测重置
// 拿到任何消息都说明当前连接是正常的
this.heartCheck();
this.onmessage(event);
};
}
reconnect() {
if (this.opts.repeatLimit > 0 && this.opts.repeatLimit <= this.repeatNum) return; // limit repeatNum the number
if (this.lockReconnect || this.forbidReconnect) return;
this.lockReconnect = true;
this.repeatNum++; // 必须在lockReconnect之后,避免进行无效计数
this.onreconnect();
// 没连接上会一直重连,设置延迟避免请求过多
setTimeout(() => {
this.createWebSocket();
this.lockReconnect = false;
}, this.opts.reconnectTimeout);
}
send(msg) {
this.ws.send(msg);
}
// 心跳检测
heartCheck() {
this.heartReset();
this.heartStart();
}
heartStart() {
if (this.forbidReconnect) return; // 不再重连就不再执行心跳
this.pingTimeoutId = setTimeout(() => {
// 这里发送一个心跳,后端收到后,返回一个心跳消息,
// onmessage拿到返回的心跳就说明连接正常
this.ws.send(this.opts.pingMsg);
// 如果超过一定时间还没重置,说明后端主动断开了
this.pongTimeoutId = setTimeout(() => {
// 如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
console.log("heart break---");
this.ws.close();
}, this.opts.pongTimeout);
}, this.opts.pingTimeout);
}
heartReset() {
clearTimeout(this.pingTimeoutId);
clearTimeout(this.pongTimeoutId);
}
close() {
console.log("手动关闭socket");
// 如果手动关闭连接,不再重连
this.forbidReconnect = true;
this.heartReset();
this.ws.close();
}
}
export default SocketPlugin;
07-02
1970
01-15
3277
09-01
2098