squidGame/tgx-games-client/assets/module_basic/scripts/WebsocketClient.ts

147 lines
4.9 KiB
TypeScript
Raw Normal View History

2025-02-07 10:49:34 +08:00
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<ServiceType> = 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<ServiceType> {
return this._conn;
}
createConnection(serverUrls: Readonly<string[]>) {
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<T extends keyof ServiceType['msg']>(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<T extends keyof ServiceType['msg']>(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<T extends keyof ServiceType['msg']>(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<T extends string & keyof ServiceType['api']>(apiName: T, req: ServiceType['api'][T]['req'], options?: any): Promise<ApiReturn<ServiceType['api'][T]['res']>> {
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;
}
}