zero-remote
Advanced tools
| "use strict"; | ||
| var __importDefault = (this && this.__importDefault) || function (mod) { | ||
| return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
| }; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.ZeroRemoteClient = void 0; | ||
| const ws_1 = __importDefault(require("ws")); | ||
| const zero_mvc_1 = require("zero-mvc"); | ||
| const IZeroRomeote_1 = require("./IZeroRomeote"); | ||
| /** | ||
| * 错误错误会弹窗 | ||
| * 重连多次后会弹窗 | ||
| */ | ||
| /** | ||
| * 与后端协议 | ||
| * 所有数据以IMessage接收和发送 | ||
| * 只支持一级属性是个回调函数 | ||
| */ | ||
| class ZeroRemoteClient extends zero_mvc_1.ZeroDispatcher { | ||
| constructor(url) { | ||
| super(); | ||
| this.url = url; | ||
| this.relinkMaxCount = 3; | ||
| this.relinkTime = 2000; | ||
| /** | ||
| * 回调函数缓存个数 | ||
| */ | ||
| this.callBackMaxIndex = 1000; | ||
| this.outTime = 1; //整秒 | ||
| this.heartbeatTime = 5; //整秒=5 | ||
| this.pack = IZeroRomeote_1.jsonPack; | ||
| this.isOpen = false; | ||
| this.isBusy = false; | ||
| this.isRelink = true; | ||
| this.relinkCount = 0; | ||
| this.router = new zero_mvc_1.ZeroDispatcher(); | ||
| this.callbackPool = {}; | ||
| this.ci = 0; | ||
| this.pingIndex = 0; | ||
| this.pingTime = 0; | ||
| this._mask = 0; | ||
| this.isMask = false; | ||
| setInterval(() => { | ||
| if (this.isOpen) { | ||
| if (this.pingIndex == this.heartbeatTime + this.outTime) { | ||
| this.mask++; | ||
| } | ||
| else if (this.pingIndex == this.heartbeatTime) { | ||
| this.pingTimeStart = new Date(); | ||
| this.ws.send(this.pack.stringify({ data: this.pingTime })); | ||
| } | ||
| this.pingIndex++; | ||
| } | ||
| }, 1000); | ||
| } | ||
| get mask() { | ||
| return this._mask; | ||
| } | ||
| set mask(value) { | ||
| let isMask = value > 0; | ||
| if (this.isMask != isMask) { | ||
| this.isMask = isMask; | ||
| if (isMask) { | ||
| this.emit("showMask"); | ||
| } | ||
| else { | ||
| this.emit("hideMask"); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * 本条结构协议 | ||
| * @param route 要发送的路由名 | ||
| * @returns | ||
| */ | ||
| getSender(route) { | ||
| return new Proxy({}, { | ||
| get: (target, p, receiver) => { | ||
| return (data) => { | ||
| return new Promise((resolve, reject) => { | ||
| this.send(route, p, data, (isError, value) => { | ||
| if (isError) { | ||
| resolve(value); | ||
| } | ||
| else { | ||
| reject(value); | ||
| this.emit("error", value); | ||
| } | ||
| }); | ||
| }); | ||
| }; | ||
| } | ||
| }); | ||
| } | ||
| getReceiver(r) { | ||
| return new Proxy({}, { | ||
| get: (target, p, receiver) => { | ||
| return (data) => { | ||
| this.receive(r, p, data); | ||
| }; | ||
| } | ||
| }); | ||
| } | ||
| send(route, key, data, callback) { | ||
| if (this.isOpen) { | ||
| if (!this.mask) { | ||
| let cbs = undefined; | ||
| for (const key in data) { | ||
| if (data.hasOwnProperty(key)) { | ||
| const element = data[key]; | ||
| if (typeof element == "function") { | ||
| this.ci++; | ||
| delete this.callbackPool[this.ci - this.callBackMaxIndex]; | ||
| this.callbackPool[this.ci] = element; | ||
| if (cbs == null) { | ||
| cbs = {}; | ||
| } | ||
| cbs[key] = this.ci; | ||
| } | ||
| } | ||
| } | ||
| let index = undefined; | ||
| if (callback != null) { | ||
| this.ci++; | ||
| delete this.callbackPool[this.ci - this.callBackMaxIndex]; | ||
| index = this.ci; | ||
| this.callbackPool[this.ci] = callback; | ||
| } | ||
| this.ws.send(this.pack.stringify({ route: route, key: key, data: data, cbs: cbs, index: index })); | ||
| } | ||
| else { | ||
| // console.log("弱网环境,send信息被忽略" + route) | ||
| callback(false, "弱网环境,send信息被忽略"); | ||
| } | ||
| } | ||
| else { | ||
| // console.log("游戏服务器未连接,send信息被忽略" + route) | ||
| callback(false, "服务器未连接,send信息被忽略"); | ||
| } | ||
| } | ||
| receive(route, key, callback) { | ||
| this.router.on(route + "." + key, callback); | ||
| } | ||
| reLink() { | ||
| if (this.relinkCount < this.relinkMaxCount) { | ||
| this.relinkTimeOut = setTimeout(() => { | ||
| this.relinkTimeOut == null; | ||
| this.relinkCount++; | ||
| this.link(); | ||
| }, this.relinkTime); | ||
| } | ||
| else { | ||
| this.relinkCount = 0; | ||
| this.emit("popup"); | ||
| } | ||
| } | ||
| message(value) { | ||
| let obj; | ||
| try { | ||
| obj = this.pack.parse(value); | ||
| } | ||
| catch (_a) { | ||
| throw new Error("服务器数据无法序列化"); | ||
| } | ||
| this.pong(); | ||
| if (obj.code == null) { | ||
| if (obj.route != null) { | ||
| if (obj.key == null) { | ||
| throw new Error("服务器数据出错"); | ||
| } | ||
| else { | ||
| this.router.emit(obj.route + "." + obj.key, obj.data); | ||
| } | ||
| } | ||
| else { | ||
| // pingTimeStart() | ||
| // this.pingTime = new Date() | ||
| this.pingTime = new Date().getTime() - this.pingTimeStart.getTime(); | ||
| } | ||
| } | ||
| else if (obj.code == IZeroRomeote_1.ReportCode.CALLBACK) { | ||
| if (obj.ci != null) { | ||
| let method = this.callbackPool[obj.ci]; | ||
| if (method) { | ||
| method.apply(this, obj.args); | ||
| delete this.callbackPool[obj.ci]; | ||
| } | ||
| } | ||
| } | ||
| else if (obj.code == IZeroRomeote_1.ReportCode.KICK) { | ||
| this.close(); | ||
| } | ||
| else { | ||
| this.emit("error", obj.error); | ||
| } | ||
| } | ||
| pong() { | ||
| this.emit("heartbeat"); | ||
| this.pingIndex = 0; | ||
| this.mask--; | ||
| } | ||
| /** | ||
| * 这个callback 在重连里不会触发 | ||
| * 如需要触发 请使用 on("linked") | ||
| * @param callback | ||
| */ | ||
| link(callback) { | ||
| this.isRelink = true; | ||
| if (this.url == "" || this.url == null) { | ||
| throw new Error("服务器地址为空"); | ||
| } | ||
| else { | ||
| if (this.isBusy) { | ||
| throw new Error("重复连接服务"); | ||
| } | ||
| else { | ||
| this.ws = new ws_1.default(this.url); | ||
| this.isBusy = true; | ||
| this.emit("linking"); | ||
| this.ws.onerror = () => { | ||
| this.emit("error", "网络出错"); | ||
| }; | ||
| this.ws.onopen = () => { | ||
| this.mask = 0; | ||
| this.relinkCount = 0; | ||
| this.isOpen = true; | ||
| this.emit("linked"); | ||
| if (callback) { | ||
| callback(); | ||
| } | ||
| }; | ||
| this.ws.onclose = () => { | ||
| this.mask = 0; | ||
| this.isOpen = false; | ||
| this.isBusy = false; | ||
| this.emit("suspend"); | ||
| for (const key in this.callbackPool) { | ||
| if (Object.prototype.hasOwnProperty.call(this.callbackPool, key)) { | ||
| const element = this.callbackPool[key]; | ||
| element(false, "网络断开"); | ||
| delete this.callbackPool[key]; | ||
| } | ||
| } | ||
| if (this.isRelink) { | ||
| this.reLink(); | ||
| } | ||
| else { | ||
| this.emit("stop"); | ||
| } | ||
| }; | ||
| this.ws.onmessage = (evt) => { | ||
| this.message(evt.data.toString()); | ||
| }; | ||
| } | ||
| } | ||
| } | ||
| close() { | ||
| if (this.relinkTimeOut) { | ||
| clearTimeout(this.relinkTimeOut); | ||
| this.relinkTimeOut == null; | ||
| } | ||
| this.isRelink = false; | ||
| this.isOpen = false; | ||
| this.ws.close(); | ||
| } | ||
| } | ||
| exports.ZeroRemoteClient = ZeroRemoteClient; |
+1
-1
| { | ||
| "name": "zero-remote", | ||
| "version": "1.2.2", | ||
| "version": "1.2.3", | ||
| "description": "常连接网络", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
43192
25.27%10
11.11%1117
31.41%