121 lines
3.3 KiB
TypeScript
Raw Normal View History

2022-12-01 22:26:41 +08:00
import Singleton from '../Base/Singleton'
2022-12-07 22:24:46 +08:00
import { ApiMsgEnum, IModel } 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-07 22:24:46 +08:00
interface IItem {
cb: Function;
ctx: unknown;
}
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-07 22:24:46 +08:00
maps: Map<ApiMsgEnum, Array<IItem>> = 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-07 22:24:46 +08:00
//onmessage接受的数据类型只有在后端返回字节数组的时候才有效果
2022-12-04 22:10:30 +08:00
this.ws.binaryType = 'arraybuffer';
2022-12-07 22:24:46 +08:00
2022-12-01 22:26:41 +08:00
this.ws.onopen = () => {
this.isConnected = true
resolve(true)
}
2022-12-07 22:24:46 +08:00
this.ws.onerror = (e) => {
2022-12-01 22:26:41 +08:00
this.isConnected = false
2022-12-07 22:24:46 +08:00
console.log(e)
2022-12-01 22:26:41 +08:00
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-07 22:24:46 +08:00
this.maps.get(name).forEach(({ cb, ctx }) => cb.call(ctx, data))
2022-12-01 22:26:41 +08:00
}
} catch (error) {
2022-12-07 22:24:46 +08:00
console.log("onmessage:", 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') })
2022-12-07 22:24:46 +08:00
this.unlistenMsg(name as any, cb, null)
2022-12-01 22:26:41 +08:00
}, TIMEOUT)
// 回调处理
2022-12-03 20:06:57 +08:00
const cb = (res) => {
2022-12-01 22:26:41 +08:00
resolve(res)
clearTimeout(timer)
2022-12-07 22:24:46 +08:00
this.unlistenMsg(name as any, cb, null)
2022-12-01 22:26:41 +08:00
}
2022-12-07 22:24:46 +08:00
this.listenMsg(name as any, cb, null)
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) {
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
}
2022-12-07 22:24:46 +08:00
listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
2022-12-04 22:10:30 +08:00
if (this.maps.has(name)) {
2022-12-07 22:24:46 +08:00
this.maps.get(name).push({ ctx, cb })
2022-12-03 20:06:57 +08:00
} else {
2022-12-07 22:24:46 +08:00
this.maps.set(name, [{ ctx, cb }])
2022-12-03 20:06:57 +08:00
}
}
2022-12-07 22:24:46 +08:00
unlistenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
2022-12-04 22:10:30 +08:00
if (this.maps.has(name)) {
2022-12-07 22:24:46 +08:00
const items = this.maps.get(name)
const index = items.findIndex(i => cb === i.cb && i.ctx === ctx);
index > -1 && items.splice(index, 1)
2022-12-03 20:06:57 +08:00
}
}
2022-12-01 22:26:41 +08:00
}