|
@@ -1,173 +0,0 @@
|
|
-interface SocketOptions {
|
|
|
|
- heartbeatInterval?: number;
|
|
|
|
- reconnectInterval?: number;
|
|
|
|
- maxReconnectAttempts?: number;
|
|
|
|
- isReconnect?: boolean;
|
|
|
|
- uid?: string;
|
|
|
|
- trans?: string;
|
|
|
|
- notice?:string;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-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: 2 * 1000, // 心跳间隔
|
|
|
|
- reconnectInterval: 4 * 1000, // 重连间隔
|
|
|
|
- maxReconnectAttempts: 99, // 最大重连次数
|
|
|
|
- isReconnect: true, // 是否需要重连
|
|
|
|
- uid: '', // 用户id
|
|
|
|
- trans: '', // 订阅的频道
|
|
|
|
- notice: '', // 订阅的频道
|
|
|
|
- ...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) {
|
|
|
|
- // this.reconnectAttempts=0;
|
|
|
|
- this.startSubscribe();
|
|
|
|
- this.startHeartbeat();
|
|
|
|
- this.emit('open', event);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- onMessage(event: MessageEvent) {
|
|
|
|
- this.emit('message', event);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- onError(event: Event) {
|
|
|
|
- console.error('WebSocket error:', event);
|
|
|
|
- this.emit('error', event);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- onClose(event: CloseEvent) {
|
|
|
|
- this.stopHeartbeat();
|
|
|
|
- this.emit('close', event);
|
|
|
|
-
|
|
|
|
- // @ts-ignore
|
|
|
|
- if (this.opts.isReconnect) {
|
|
|
|
- this.reConnect();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- reConnect() {
|
|
|
|
- // @ts-ignore
|
|
|
|
- if (this.reconnectAttempts < this.opts.maxReconnectAttempts) {
|
|
|
|
- setTimeout(() => {
|
|
|
|
- this.reconnectAttempts++;
|
|
|
|
- this.init();
|
|
|
|
- }, this.opts.reconnectInterval);
|
|
|
|
- } else {
|
|
|
|
- console.error('已到达重连次数最高,请手动刷新重连');
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- startHeartbeat() {
|
|
|
|
- if (!this.opts.heartbeatInterval) return;
|
|
|
|
- this.heartbeatInterval = window.setInterval(() => {
|
|
|
|
- if (this.ws?.readyState === WebSocket.OPEN) {
|
|
|
|
- this.send({
|
|
|
|
- id: '',
|
|
|
|
- type: 2,
|
|
|
|
- from: this.opts.uid,
|
|
|
|
- to: 'sys',
|
|
|
|
- timestamps: new Date().getTime(),
|
|
|
|
- body: 'PING',
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- }, this.opts.heartbeatInterval);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- startSubscribe() {
|
|
|
|
- // @ts-ignore
|
|
|
|
- const moreTime = this.opts.heartbeatInterval + 100;
|
|
|
|
- setTimeout(() => {
|
|
|
|
- if (!this.opts.trans) return;
|
|
|
|
- this.send({
|
|
|
|
- id: '',
|
|
|
|
- type: 8,
|
|
|
|
- from: this.opts.uid,
|
|
|
|
- to: this.opts.trans,
|
|
|
|
- timestamps: new Date().getTime(),
|
|
|
|
- body: 'subscribe',
|
|
|
|
- });
|
|
|
|
- if (this.opts.notice) {
|
|
|
|
- this.send({
|
|
|
|
- id: '',
|
|
|
|
- type: 8,
|
|
|
|
- from: this.opts.uid,
|
|
|
|
- to: this.opts.notice,
|
|
|
|
- timestamps: new Date().getTime(),
|
|
|
|
- body: 'subscribe',
|
|
|
|
- });
|
|
|
|
- }
|
|
|
|
- }, moreTime);
|
|
|
|
- }
|
|
|
|
- stopHeartbeat() {
|
|
|
|
- if (this.heartbeatInterval) {
|
|
|
|
- clearInterval(this.heartbeatInterval);
|
|
|
|
- this.heartbeatInterval = null;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- send(data: any) {
|
|
|
|
- if (this.ws?.readyState === WebSocket.OPEN) {
|
|
|
|
- this.ws.send(JSON.stringify(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));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- close() {
|
|
|
|
- this.opts.isReconnect = false;
|
|
|
|
- this.ws?.close();
|
|
|
|
- this.ws = null;
|
|
|
|
- this.stopHeartbeat();
|
|
|
|
- this.listeners = {};
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-export function useSocket(url: string, opts?: SocketOptions) {
|
|
|
|
- const socket = new Socket(url, opts);
|
|
|
|
- return {
|
|
|
|
- socket,
|
|
|
|
- close: socket.close.bind(socket),
|
|
|
|
- send: socket.send.bind(socket),
|
|
|
|
- on: socket.on.bind(socket),
|
|
|
|
- off: socket.off.bind(socket),
|
|
|
|
- };
|
|
|
|
-}
|
|
|