237 lines
6.5 KiB
TypeScript
237 lines
6.5 KiB
TypeScript
import { BaseServiceType } from 'tsrpc-browser';
|
|
import { NetEvent } from './NetEvent';
|
|
|
|
/**
|
|
* WebSocket 连接状态
|
|
*/
|
|
export enum WsConnectionStatus {
|
|
/** 已断开 */
|
|
Disconnected = "disconnected",
|
|
/** 连接中 */
|
|
Connecting = "connecting",
|
|
/** 已连接 */
|
|
Connected = "connected",
|
|
/** 连接失败 */
|
|
Failed = "failed"
|
|
}
|
|
|
|
/**
|
|
* WebSocket 客户端接口
|
|
* 统一 HTTP 和 WebSocket 客户端的接口
|
|
*/
|
|
export interface INetClient<T extends BaseServiceType = any> {
|
|
/** 调用API */
|
|
callApi<Req, Res>(apiName: string, req: Req): Promise<{ isSucc: boolean; res?: Res; err?: any }>;
|
|
|
|
/** 监听消息 (仅 WebSocket) */
|
|
listenMsg?(msgName: string, handler: Function): void;
|
|
|
|
/** 取消监听消息 (仅 WebSocket) */
|
|
unlistenMsg?(msgName: string, handler?: Function): void;
|
|
|
|
/** 发送消息 (仅 WebSocket) */
|
|
sendMsg?(msgName: string, msg: any): void;
|
|
|
|
/** 连接 (仅 WebSocket) */
|
|
connect?(): Promise<{ isSucc: boolean; errMsg?: string }>;
|
|
|
|
/** 断开连接 (仅 WebSocket) */
|
|
disconnect?(): void;
|
|
|
|
/** 获取连接状态 */
|
|
status?: WsConnectionStatus;
|
|
}
|
|
|
|
/**
|
|
* WebSocket 客户端包装器
|
|
* 提供统一的接口和事件处理
|
|
*/
|
|
export class WebSocketClientWrapper<T extends BaseServiceType = any> implements INetClient<T> {
|
|
private _wsClient: any = null;
|
|
private _status: WsConnectionStatus = WsConnectionStatus.Disconnected;
|
|
private _eventCallbacks: Map<string, Function[]> = new Map();
|
|
|
|
constructor(wsClient: any) {
|
|
this._wsClient = wsClient;
|
|
this.setupEventHandlers();
|
|
}
|
|
|
|
/**
|
|
* 设置事件处理器
|
|
*/
|
|
private setupEventHandlers(): void {
|
|
if (!this._wsClient) return;
|
|
|
|
// 监听连接事件
|
|
this._wsClient.flows.preConnectFlow.push((v: any) => {
|
|
this._status = WsConnectionStatus.Connecting;
|
|
this.emit(NetEvent.Connecting);
|
|
return v;
|
|
});
|
|
|
|
this._wsClient.flows.postConnectFlow.push((v: any) => {
|
|
if (v.isSucc) {
|
|
this._status = WsConnectionStatus.Connected;
|
|
this.emit(NetEvent.Connected);
|
|
} else {
|
|
this._status = WsConnectionStatus.Failed;
|
|
this.emit(NetEvent.Error, v.errMsg);
|
|
}
|
|
return v;
|
|
});
|
|
|
|
// 监听断开连接事件
|
|
this._wsClient.flows.postDisconnectFlow.push((v: any) => {
|
|
this._status = WsConnectionStatus.Disconnected;
|
|
this.emit(NetEvent.Disconnected);
|
|
return v;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 连接服务器
|
|
*/
|
|
async connect(): Promise<{ isSucc: boolean; errMsg?: string }> {
|
|
try {
|
|
this._status = WsConnectionStatus.Connecting;
|
|
const result = await this._wsClient.connect();
|
|
|
|
if (result.isSucc) {
|
|
this._status = WsConnectionStatus.Connected;
|
|
} else {
|
|
this._status = WsConnectionStatus.Failed;
|
|
}
|
|
|
|
return result;
|
|
} catch (error) {
|
|
this._status = WsConnectionStatus.Failed;
|
|
return {
|
|
isSucc: false,
|
|
errMsg: error instanceof Error ? error.message : String(error)
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 断开连接
|
|
*/
|
|
disconnect(): void {
|
|
if (this._wsClient && typeof this._wsClient.disconnect === 'function') {
|
|
this._wsClient.disconnect();
|
|
}
|
|
this._status = WsConnectionStatus.Disconnected;
|
|
}
|
|
|
|
/**
|
|
* 调用API
|
|
*/
|
|
async callApi<Req, Res>(apiName: string, req: Req): Promise<{ isSucc: boolean; res?: Res; err?: any }> {
|
|
if (this._status !== WsConnectionStatus.Connected) {
|
|
return {
|
|
isSucc: false,
|
|
err: 'WebSocket not connected'
|
|
};
|
|
}
|
|
|
|
try {
|
|
return await this._wsClient.callApi(apiName, req);
|
|
} catch (error) {
|
|
return {
|
|
isSucc: false,
|
|
err: error
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 监听消息
|
|
*/
|
|
listenMsg(msgName: string, handler: Function): void {
|
|
if (this._wsClient && typeof this._wsClient.listenMsg === 'function') {
|
|
this._wsClient.listenMsg(msgName, handler);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 取消监听消息
|
|
*/
|
|
unlistenMsg(msgName: string, handler?: Function): void {
|
|
if (this._wsClient && typeof this._wsClient.unlistenMsg === 'function') {
|
|
this._wsClient.unlistenMsg(msgName, handler);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 发送消息
|
|
*/
|
|
sendMsg(msgName: string, msg: any): void {
|
|
if (this._status !== WsConnectionStatus.Connected) {
|
|
console.warn('[WebSocketClient] Cannot send message: not connected');
|
|
return;
|
|
}
|
|
|
|
if (this._wsClient && typeof this._wsClient.sendMsg === 'function') {
|
|
this._wsClient.sendMsg(msgName, msg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 注册事件监听器
|
|
*/
|
|
on(event: NetEvent, callback: Function): void {
|
|
if (!this._eventCallbacks.has(event)) {
|
|
this._eventCallbacks.set(event, []);
|
|
}
|
|
this._eventCallbacks.get(event)!.push(callback);
|
|
}
|
|
|
|
/**
|
|
* 取消事件监听器
|
|
*/
|
|
off(event: NetEvent, callback: Function): void {
|
|
const callbacks = this._eventCallbacks.get(event);
|
|
if (callbacks) {
|
|
const index = callbacks.indexOf(callback);
|
|
if (index > -1) {
|
|
callbacks.splice(index, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 触发事件
|
|
*/
|
|
private emit(event: NetEvent, ...args: any[]): void {
|
|
const callbacks = this._eventCallbacks.get(event);
|
|
if (callbacks) {
|
|
callbacks.forEach(callback => {
|
|
try {
|
|
callback(...args);
|
|
} catch (error) {
|
|
console.error('[WebSocketClient] Event callback error:', error);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取连接状态
|
|
*/
|
|
get status(): WsConnectionStatus {
|
|
return this._status;
|
|
}
|
|
|
|
/**
|
|
* 判断是否已连接
|
|
*/
|
|
get isConnected(): boolean {
|
|
return this._status === WsConnectionStatus.Connected;
|
|
}
|
|
|
|
/**
|
|
* 获取原始客户端实例
|
|
*/
|
|
get rawClient(): any {
|
|
return this._wsClient;
|
|
}
|
|
} |