2022-12-01 22:26:41 +08:00
|
|
|
|
import Singleton from '../Base/Singleton'
|
2022-12-04 22:10:30 +08:00
|
|
|
|
import { ApiMsgEnum, IModel, strdecode, strencode } from '../Common';
|
2022-12-05 21:46:02 +08:00
|
|
|
|
import { binaryEncode, binaryDecode } from '../Common/Binary';
|
2022-12-01 22:26:41 +08:00
|
|
|
|
|
|
|
|
|
const TIMEOUT = 5000
|
|
|
|
|
|
2022-12-03 20:06:57 +08:00
|
|
|
|
export interface ICallApiRet<T> {
|
2022-12-01 22:26:41 +08:00
|
|
|
|
success: boolean;
|
|
|
|
|
error?: Error;
|
2022-12-03 20:06:57 +08:00
|
|
|
|
res?: T
|
2022-12-01 22:26:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 20:06:57 +08:00
|
|
|
|
type aaa = keyof IModel
|
2022-12-01 22:26:41 +08:00
|
|
|
|
export default class NetworkManager extends Singleton {
|
|
|
|
|
static get Instance() {
|
|
|
|
|
return super.GetInstance<NetworkManager>()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ws: WebSocket
|
|
|
|
|
port = 8888
|
2022-12-04 22:10:30 +08:00
|
|
|
|
maps: Map<ApiMsgEnum, Function[]> = new Map()
|
2022-12-01 22:26:41 +08:00
|
|
|
|
isConnected = false
|
|
|
|
|
|
|
|
|
|
connect() {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
2022-12-03 21:28:38 +08:00
|
|
|
|
if (this.isConnected) {
|
|
|
|
|
resolve(true)
|
|
|
|
|
return
|
|
|
|
|
}
|
2022-12-01 22:26:41 +08:00
|
|
|
|
this.ws = new WebSocket(`ws://localhost:${this.port}`)
|
2022-12-04 22:10:30 +08:00
|
|
|
|
|
|
|
|
|
this.ws.binaryType = 'arraybuffer';
|
2022-12-01 22:26:41 +08:00
|
|
|
|
this.ws.onopen = () => {
|
|
|
|
|
console.log("ws onopen")
|
|
|
|
|
this.isConnected = true
|
|
|
|
|
resolve(true)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.ws.onerror = () => {
|
|
|
|
|
this.isConnected = false
|
|
|
|
|
reject("ws onerror")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.ws.onclose = () => {
|
|
|
|
|
this.isConnected = false
|
|
|
|
|
reject("ws onclose")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.ws.onmessage = (e) => {
|
|
|
|
|
try {
|
2022-12-04 22:10:30 +08:00
|
|
|
|
const json = binaryDecode(e.data)
|
2022-12-01 22:26:41 +08:00
|
|
|
|
const { name, data } = json
|
|
|
|
|
try {
|
2022-12-04 22:10:30 +08:00
|
|
|
|
if (this.maps.has(name) && this.maps.get(name).length) {
|
2022-12-01 22:26:41 +08:00
|
|
|
|
console.log(json);
|
2022-12-04 22:10:30 +08:00
|
|
|
|
this.maps.get(name).forEach(cb => cb(data))
|
2022-12-01 22:26:41 +08:00
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
2022-12-04 22:10:30 +08:00
|
|
|
|
console.log("this.maps.get(name).forEach(cb => cb(restData))", error)
|
2022-12-01 22:26:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log('解析失败,不是合法的JSON格式', error)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 20:06:57 +08:00
|
|
|
|
callApi<T extends keyof IModel['api']>(name: T, data: IModel['api'][T]['req']): Promise<ICallApiRet<IModel['api'][T]['res']>> {
|
|
|
|
|
return new Promise((resolve) => {
|
2022-12-01 22:26:41 +08:00
|
|
|
|
try {
|
|
|
|
|
// 超时处理
|
|
|
|
|
const timer = setTimeout(() => {
|
|
|
|
|
resolve({ success: false, error: new Error('timeout') })
|
|
|
|
|
this.unlistenMsg(name, cb)
|
|
|
|
|
}, TIMEOUT)
|
|
|
|
|
|
|
|
|
|
// 回调处理
|
2022-12-03 20:06:57 +08:00
|
|
|
|
const cb = (res) => {
|
2022-12-01 22:26:41 +08:00
|
|
|
|
resolve(res)
|
|
|
|
|
clearTimeout(timer)
|
|
|
|
|
this.unlistenMsg(name, cb)
|
|
|
|
|
}
|
2022-12-03 20:06:57 +08:00
|
|
|
|
this.listenMsg(name as any, cb)
|
2022-12-01 22:26:41 +08:00
|
|
|
|
|
2022-12-04 22:10:30 +08:00
|
|
|
|
this.sendMsg(name as any, data)
|
2022-12-01 22:26:41 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(error)
|
|
|
|
|
resolve({ success: false, error: error as Error })
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2022-12-03 20:06:57 +08:00
|
|
|
|
|
2022-12-06 23:10:03 +08:00
|
|
|
|
async sendMsg<T extends keyof IModel['msg']>(name: T, data: IModel['msg'][T]) {
|
2022-12-04 22:10:30 +08:00
|
|
|
|
const view = binaryEncode(name, data)
|
2022-12-06 23:10:03 +08:00
|
|
|
|
let networkLag = parseInt(new URLSearchParams(location.search).get('lag') || '0') || 0;
|
|
|
|
|
await new Promise((r) => setTimeout(r, networkLag))
|
2022-12-04 22:10:30 +08:00
|
|
|
|
this.ws.send(view.buffer)
|
2022-12-03 20:06:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void) {
|
2022-12-04 22:10:30 +08:00
|
|
|
|
if (this.maps.has(name)) {
|
|
|
|
|
this.maps.get(name).push(cb)
|
2022-12-03 20:06:57 +08:00
|
|
|
|
} else {
|
2022-12-04 22:10:30 +08:00
|
|
|
|
this.maps.set(name, [cb])
|
2022-12-03 20:06:57 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-04 22:10:30 +08:00
|
|
|
|
unlistenMsg(name: ApiMsgEnum, cb: Function) {
|
|
|
|
|
if (this.maps.has(name)) {
|
|
|
|
|
const index = this.maps.get(name).indexOf(cb)
|
|
|
|
|
index > -1 && this.maps.get(name).splice(index, 1)
|
2022-12-03 20:06:57 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-01 22:26:41 +08:00
|
|
|
|
}
|