import { ApiReturn, WsClient } from "tsrpc-browser"; import { ServiceType } from "../shared/protocols/serviceProto_public"; import { NetUtil } from "./NetUtil"; export class WebsocketClient { public static EVENT_DISCONNECTED = 'WebsocketClient.EVENT_DISCONNECTED'; protected _conn: WsClient = null; protected _serverUrl = ''; protected _eventHandlers: { [key: string]: { event: string, func: Function, thisArg: any }[] } = {}; protected _handlers: { msg: string, func: Function, handler: Function, thisArg: any }[] = []; public get conn(): WsClient { return this._conn; } createConnection(serverUrls: Readonly) { if (this._conn) { this._conn.disconnect(1000, 'switch_server'); } let index = Math.floor(serverUrls.length * Math.random()); let serverUrl = serverUrls[index]; this._serverUrl = serverUrl; this._conn = NetUtil.createWebsocketClient(this._serverUrl); this._conn.flows.postDisconnectFlow.push(v => { this._dispatchEvent(WebsocketClient.EVENT_DISCONNECTED, v); return v; }); /* this._conn.flows.postRecvMsgFlow.push(v=>{ console.log(v.msgName,v.msg); return v; }); */ } on(event: string, func: Function, thisArg?: any) { let handler = func; if (thisArg) { handler = func.bind(thisArg); } let handlers = this._eventHandlers[event] || []; handlers.push({ event: event, func: func, thisArg: thisArg }); this._eventHandlers[event] = handlers; } off(event: string, func?: Function, thisArg?: any) { let handlers = this._eventHandlers[event]; if (handlers) { for (let i = 0; i < handlers.length; ++i) { let item = handlers[i]; if (item.func === func && item.thisArg == thisArg) { handlers.splice(i, 1); return; } } } } private _dispatchEvent(event: string, args) { let handlers = this._eventHandlers[event]; if (handlers) { for (let i = 0; i < handlers.length; ++i) { let item = handlers[i]; item.func.call(item.thisArg, args); } } } startPing() { setInterval(() => { if (this._conn.isConnected) { //console.log('ping'); this._conn.sendMsg('Ping', {}); } }, 5000); } public get serverUrl(): string { return this._serverUrl; } public listenMsg(msgName: T | RegExp, func: Function, thisArg?: any) { let handler = func; if (thisArg) { handler = func.bind(thisArg); } // console.log("添加监听 001",this._handlers); // console.log("添加监听 002",this._conn); this._handlers.push({ msg: msgName as string, func: func, handler: handler, thisArg: thisArg }); this._conn.listenMsg(msgName, handler as any); } public unlistenMsg(msgName: T | RegExp, func: Function, thisArg?: any) { for (let i = 0; i < this._handlers.length; ++i) { let item = this._handlers[i]; if (item.msg === msgName && item.func === func || item.thisArg == thisArg) { // console.log("移除监听前 001====", item); this._handlers.splice(i, 1); this._conn.unlistenMsg(msgName, item.handler); item = null; break; } } console.log("移除监听后 002====", this._handlers); } public unlistenMsgAll(msgName: T | RegExp): void { for (let i = this._handlers.length - 1; i >= 0; --i) { let item = this._handlers[i]; if (item.msg === msgName) { this._handlers.splice(i, 1); } } this._conn.unlistenMsgAll(msgName); console.log("移除监听后", this._handlers); } public callApi(apiName: T, req: ServiceType['api'][T]['req'], options?: any): Promise> { return this._conn.callApi(apiName, req, options); } public async ensureConnected() { let ret = await this._connect(); return ret; } disconnect() { this._conn.disconnect(); } private async _connect(): Promise<{ isSucc: boolean, err?: {code?:string, message: string } }> { // Connect let resConnect = await this._conn.connect(); if (!resConnect.isSucc) { return { isSucc: false, err: { message: resConnect.errMsg } }; } return { isSucc: true }; } public get subRoomDisplayName() { return this.subRoomDisplayName; } }