diff --git a/src/common/ClientConnection.ts b/src/common/ClientConnection.ts index 1bb153f..598803f 100644 --- a/src/common/ClientConnection.ts +++ b/src/common/ClientConnection.ts @@ -6,6 +6,33 @@ import SubtitleEntity from "src/entities/SubtitleEntity"; import { Protocol } from "src/entities/WSProtocol"; import EventBus, { EventNamesDefine } from "./EventBus"; +class _RpcInfo { + send_timestamp: number; + timeout_timestamp: number; + callback: (is_fail: boolean, packet: Protocol.Commands, data: string) => void; + + constructor( + timeout_timestamp: number, + callback: ( + is_fail: boolean, + packet: Protocol.Commands, + data: string + ) => void + ) { + this.timeout_timestamp = timeout_timestamp; + this.send_timestamp = new Date().getTime(); + this.callback = callback; + } + + public reject() { + this.callback(true, new Protocol.Commands(), ""); + } + + public reslove(is_fail: boolean, packet: Protocol.Commands, data: string) { + this.callback(is_fail, packet, data); + } +} + export default class ClientConnection { ws: WebSocket | null = null; url = ""; @@ -13,10 +40,7 @@ export default class ClientConnection { password = ""; _is_login = false; _rpc_id_counter = 0; - rpc_map = new Map< - number, - (is_fail: boolean, packet: Protocol.Commands, data: string) => void - >(); + rpc_map = new Map(); public login_callback: | ((this: ClientConnection, logined: boolean) => void) @@ -28,6 +52,9 @@ export default class ClientConnection { password?: string | null ) { this.reconnectTo(url, user_name, password); + setTimeout(() => { + this.checkRpcTimeout(); + }, 1000); } get is_connected() { @@ -49,6 +76,7 @@ export default class ClientConnection { this.ws?.close(); this.ws = null; } + public reconnectTo( url: string, user_name?: string | null, @@ -70,6 +98,14 @@ export default class ClientConnection { this.initializeWs(); } + checkRpcTimeout() { + const current_datetime = new Date().getTime(); + this.rpc_map.forEach((v, k, m) => { + if (current_datetime - v.send_timestamp > v.timeout_timestamp) { + } + }); + } + initializeWs() { if (this.ws) { this.ws.onclose = (ev) => { @@ -180,11 +216,8 @@ export default class ClientConnection { } } } else if (this.rpc_map.has(packet.rpc_id)) { - const f = this.rpc_map.get(packet.rpc_id); - if (f && typeof f == "function") { - f(false, packet, ev.data); - this.rpc_map.delete(packet.rpc_id); - } + this.rpc_map.get(packet.rpc_id)?.reslove(false, packet, ev.data); + this.rpc_map.delete(packet.rpc_id); } else { EventBus.getInstance().emit( packet.flag == Protocol.PacketEntity.FLAG_NOTIFY @@ -214,33 +247,36 @@ export default class ClientConnection { return new Promise((resolve, reject) => { const rpc_id = ++this._rpc_id_counter; if (this.rpc_map.has(rpc_id)) { - const f = this.rpc_map.get(rpc_id); - if (f && typeof f == "function") { - f(true, new Protocol.Commands(), ""); - this.rpc_map.delete(rpc_id); - } + this.rpc_map.get(rpc_id)?.reject(); + this.rpc_map.delete(rpc_id); } request.rpc_id = rpc_id; - this.ws?.send(JSON.stringify(request)); this.rpc_map.set( rpc_id, - (is_fail: boolean, packet: Protocol.Commands, data: string) => { - if (is_fail) { - reject(); - } else { - try { - const response = JSON.parse(data) as _ResponseType; - if (response) { - resolve(response); - } else { + new _RpcInfo( + request.timeout, + (is_fail: boolean, packet: Protocol.Commands, data: string) => { + if (is_fail) { + reject(); + } else { + try { + const response = JSON.parse(data) as _ResponseType; + if (response) { + resolve(response); + } else { + reject(); + } + } catch { reject(); } - } catch { - reject(); } } - } + ) ); + if (request) { + request.timeout; + } + this.ws?.send(JSON.stringify(request)); }); } diff --git a/src/components/SystemSettingDialog.vue b/src/components/SystemSettingDialog.vue index 837a2c8..4fc5fdc 100644 --- a/src/components/SystemSettingDialog.vue +++ b/src/components/SystemSettingDialog.vue @@ -853,9 +853,25 @@ export default defineComponent({ request.rotate = output_board_rotate.value; request.volume = output_board_volume.value; request.mute = output_board_mute.value == $t.t("on"); - GlobalData.getInstance() - .getCurrentClient() - ?.setOutputBoardSetting(request); + + let success = false; + try { + await GlobalData.getInstance() + .getCurrentClient() + ?.setOutputBoardSetting(request); + success = true; + } catch { + $q.notify({ + color: success ? "positive" : "negative", + icon: success ? "done" : "warning", + message: + $t.t("set output board") + + (success ? $t.t("success") : $t.t("fail")) + + "!", + position: "top", + timeout: 1000, + }); + } }; const apply = async () => { diff --git a/src/entities/WSProtocol.ts b/src/entities/WSProtocol.ts index 10e7afc..77788fa 100644 --- a/src/entities/WSProtocol.ts +++ b/src/entities/WSProtocol.ts @@ -296,6 +296,8 @@ export namespace Protocol { rpc_id = 0; /** 命令 */ command = Protocol.Commands.kUnKnowCommand; + /** 超时 毫秒 */ + timeout = 15 * 1000; } export class LoginRequest extends PacketEntity {