weNetworkMgr.ts 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. // import { Notifications } from '../notifications';
  2. import { Http } from "./weHttp";
  3. class networkMgr {
  4. ////////////////////////////
  5. // 类成员
  6. ///////////////////////////
  7. public static readonly _instance = new networkMgr();
  8. /** 消息ID */
  9. private mid = 0;
  10. /** 消息队列 */
  11. private messageList: any = {};
  12. /** 每条消息最多的发送次数 */
  13. private limitMessageNum = 5;
  14. /** 时间 */
  15. private timer: number | null = null;
  16. /** token */
  17. private token = '';
  18. /** 消息锁: false, 可以正常发送消息,已上锁 */
  19. private isLock = false;
  20. private _dealHeadListener: Function | null = null;
  21. /** 加密规则 */
  22. private _encryptRule = ['mid:', 'uid:', 'key:', 'data:'];
  23. /** 加密code, 服务端客户端要统一 */
  24. private _encryptCode = 'zqkg';
  25. /** 计时时间: 1s */
  26. private _intervalTime = 3000;
  27. /** 服务器报错 */
  28. private _errorServerCode = 500;
  29. /** 成功回包code */
  30. private _successCode = 0;
  31. /** 重起游戏的错误码 */
  32. private _errorRestartGameCode = [102];
  33. /** 错误码列表 */
  34. private _errorNetCode: any = {};
  35. /** 超过时间 */
  36. private _overTime = 5000;
  37. /** uid */
  38. private _uid = 0;
  39. private lastMessage = null;
  40. ////////////////////////////
  41. // get、set构造器
  42. ///////////////////////////
  43. public set errorNetCode(codes: Object) {
  44. this._errorNetCode = codes;
  45. }
  46. public set encryptCode(str: string) {
  47. this._encryptCode = str;
  48. }
  49. public set errorRestartGameCode(array: Array<number>) {
  50. this._errorRestartGameCode = array;
  51. }
  52. public set successCode(code: number) {
  53. this._successCode = code;
  54. }
  55. public set errorServerCode(code: number) {
  56. this._errorServerCode = code;
  57. }
  58. public set encryptRule(array: Array<string>) {
  59. this._encryptRule = array;
  60. }
  61. public set intervalTime(time: number) {
  62. this._intervalTime = time;
  63. }
  64. public set overTime(time: number) {
  65. this._overTime = time;
  66. }
  67. public set dealHeadListener(cb: Function) {
  68. this._dealHeadListener = cb;
  69. }
  70. public set uid(uid: number) {
  71. this._uid = uid;
  72. }
  73. ////////////////////////////
  74. // 接口
  75. ///////////////////////////
  76. public constructor() {
  77. this.mid = 0;
  78. this.messageList = {};
  79. this.timer = null;
  80. }
  81. /**
  82. * @description 发送xhr消息
  83. * @param {string} _route
  84. * @param {Object} data
  85. * @param {Function} cb
  86. * @param isRepeat 是否重复发送事件
  87. * @param fail 失败回调
  88. */
  89. public xhrPost(_route: string, data: Object, cb?: Function, fail?: Function, isRepeat = false) {
  90. this.mid += 1;
  91. // 包
  92. let msg = {
  93. head: {
  94. route: _route,
  95. mid: this.mid.toString(),
  96. uid: this._uid
  97. },
  98. body: data
  99. };
  100. // 消息队列的数据结构
  101. let netPackage = new NetworkPackage();
  102. netPackage.route = _route;
  103. netPackage.mid = this.mid;
  104. netPackage.data = msg;
  105. if (cb) {
  106. netPackage.callback = cb;
  107. }
  108. netPackage.isRepeat = isRepeat;
  109. if (fail) {
  110. netPackage.failCallBack = fail;
  111. }
  112. this.messageList[this.mid] = netPackage;
  113. // 开始计时
  114. this.startTimer();
  115. if (!this.isLock) {
  116. this.sendMessage(this.mid);
  117. }
  118. }
  119. /**
  120. * @description 检查回包
  121. * @param _respone
  122. */
  123. public checkRespone(route: any, _respone: any, mid: any) {
  124. // 解密
  125. let respone: any = this.jsdecrypt(_respone);
  126. let data = respone;
  127. // if (respone.result) {
  128. // data = this.jsdecrypt(respone.result);
  129. // }
  130. // respone = this.jsdecrypt(respone);
  131. // let head: any = respone.head;
  132. // let body: any = respone.body;
  133. // let code = head.code || 0;
  134. // let mid = 0;
  135. // 刷新token
  136. // this.token = head.token;
  137. let message = this.messageList[mid];
  138. // 头部回包处理
  139. // this.succeedResponeHead(head);
  140. // 服务端回包,返回需要的数据
  141. // if (code === this._successCode) {
  142. this.succeedResponeBody(message, data, mid);
  143. // 服务端回包中出现错误码
  144. // } else {
  145. // this.checkErrorCode(code, mid);
  146. // }
  147. }
  148. private succeedResponeHead(head: any) {
  149. if (this._dealHeadListener)
  150. this._dealHeadListener(head);
  151. }
  152. ////////////////////////////
  153. // 业务逻辑
  154. ///////////////////////////
  155. /**
  156. * @description 没有错误信息,把服务端数据发送到业务逻辑层
  157. * @param message
  158. * @param body
  159. * @param mid
  160. */
  161. private succeedResponeBody(message: any, body: any, mid: number) {
  162. this.isLock = false;
  163. this.clearTimer();
  164. this.deleteMessageListItem(mid, false);
  165. this.checkNextMessage();
  166. if (message && message.callback) {
  167. message.callback(body);
  168. }
  169. }
  170. /**
  171. * @description 网络消息code检查
  172. * @param code 错误码;需要和服务端协定
  173. * @param mid
  174. */
  175. private checkErrorCode(code: number, mid: number) {
  176. // 收到消息500 则继续重发直到发送次数限制.
  177. if (code !== this._errorServerCode) {
  178. this.deleteMessageListItem(mid, true);
  179. }
  180. // 重启游戏
  181. for (let index = 0; index < this._errorRestartGameCode.length; index++) {
  182. let errorCode = this._errorRestartGameCode[index];
  183. if (code === errorCode) {
  184. this.restartGame();
  185. }
  186. }
  187. let resultStr = this.getErrorCodeMeaning(code);
  188. console.error("----> 返回错误, code:", code, resultStr);
  189. // TODO: 把错误码信息返回给业务逻辑
  190. // Notifications.emit('sys_http_error', { code: code, mid: mid });
  191. }
  192. private checkNextMessage() {
  193. for (let key in this.messageList) {
  194. let message = this.messageList[key];
  195. if (message.sendNum === 0) {
  196. this.sendMessage(message.mid);
  197. }
  198. }
  199. }
  200. /**
  201. * @description 删除消息队列中的元素
  202. * @param mid
  203. * @param fail 是否是失败
  204. */
  205. private deleteMessageListItem(mid: number, fail: boolean) {
  206. if (this.messageList && this.messageList[mid]) {
  207. if (this.messageList[mid].failCallBack && fail) {
  208. this.messageList[mid].failCallBack();
  209. }
  210. delete this.messageList[mid];
  211. }
  212. }
  213. /**
  214. * @description 数据加密(需要和服务端约定)
  215. * @param data
  216. // */
  217. // private jsencrypt(data: any) {
  218. // // let head = data.head;
  219. // // let body = JSON.stringify(data.body);
  220. // // let encryptData = `${this._encryptRule[0]}${head.mid}&${this._encryptRule[1]}${head.uid}&${this._encryptRule[2]}${this._encryptCode}&${this._encryptRule[3]}${body}`;
  221. // // data.head.mi = Sha1.hex_hmac_sha1(this._encryptCode, encryptData).slice(5);
  222. // return data;
  223. // }
  224. /**
  225. * @description 解密
  226. * @param _data
  227. */
  228. private jsdecrypt(_data: any) {
  229. let obj = null;
  230. if (typeof _data == 'string') {
  231. try {
  232. obj = JSON.parse(_data);
  233. } catch (e) {
  234. }
  235. }
  236. // if (obj.result && obj) {
  237. // obj.result = window.DES3.decrypt(global.DES3_KEY, obj.result);
  238. // }
  239. return obj;
  240. }
  241. /**
  242. * @description 发送消息队列
  243. * @param {number} mid
  244. * @param {number} isCheck 是否检查包的发送次数是否超过上限
  245. */
  246. private sendMessage(mid: number, isCheck: boolean = true) {
  247. // 消息队列为空
  248. if (Object.keys(this.messageList).length === 0) {
  249. console.log('message list is null...');
  250. return;
  251. }
  252. let message = this.messageList[mid];
  253. // 一条消息的发送次数大于限制次数,建议重启游戏
  254. if (isCheck && message.sendNum >= this.limitMessageNum
  255. || !isCheck && message.errorNum >= this.limitMessageNum) {
  256. console.error(message.data.head.route, 'message send too much times');
  257. this.deleteMessageListItem(mid, false);
  258. // Notifications.emit('sys_http_try_too_many_time');
  259. return;
  260. }
  261. message.sendNum += 1;
  262. let data = message.data;
  263. let route = data.head.route;
  264. data.head.token = this.token;
  265. // 加密
  266. console.log('----> 请求数据', route, data.body);
  267. this.lastMessage = message;
  268. Http.post(route, data.body, mid);
  269. }
  270. /**
  271. * @description 获取错误码对应的意思
  272. * @param code
  273. */
  274. private getErrorCodeMeaning(code: number) {
  275. let errStr = this._errorNetCode[code];
  276. let resultStr = errStr;
  277. if (!errStr) {
  278. resultStr = `服务器错误码: ${code}`;
  279. }
  280. return resultStr;
  281. }
  282. /**
  283. * @description 重起游戏
  284. */
  285. private restartGame() {
  286. }
  287. /**
  288. * @description 开始定时器
  289. */
  290. private startTimer() {
  291. if (!this.timer) {
  292. this.timer = setInterval(this.checkPackage.bind(this), this._intervalTime);
  293. }
  294. }
  295. /**
  296. * @description 检查发包
  297. */
  298. private checkPackage() {
  299. if (Object.keys(this.messageList).length !== 0) {
  300. for (let key in this.messageList) {
  301. let message = this.messageList[key];
  302. let time = Date.now();
  303. if (time - message.time > this._overTime && message.isRepeat) {
  304. let mid = message.mid;
  305. this.sendMessage(mid);
  306. break;
  307. } else {
  308. this.deleteMessageListItem(message.mid, false);
  309. }
  310. }
  311. } else {
  312. this.clearTimer();
  313. }
  314. }
  315. /**
  316. * @description 清理定时器
  317. */
  318. private clearTimer() {
  319. if (this.timer) {
  320. clearInterval(this.timer);
  321. this.timer = 0;
  322. }
  323. }
  324. /**
  325. * http请求err处理
  326. * @param mid 消息id
  327. * @param error 错误内容
  328. * @param tip 错误提示文本
  329. */
  330. public onHttpError(mid: any, error?: any, tip?: string): void {
  331. if (tip)
  332. console.error("----> onHttpError", tip, error);
  333. else
  334. console.error("----> onHttpError", error);
  335. let pack: NetworkPackage = this.messageList[mid];
  336. if (pack) {
  337. //如果需要重复
  338. if (pack.isRepeat) {
  339. setTimeout(() => {
  340. pack.errorNum++
  341. this.sendMessage(mid, false);
  342. }, 3000);
  343. } else {
  344. this.deleteMessageListItem(mid, true);
  345. }
  346. }
  347. };
  348. }
  349. export const NetworkMgr = networkMgr._instance;
  350. /**
  351. * NetworkPackage
  352. * 网络包
  353. */
  354. // main
  355. export default class NetworkPackage {
  356. public route: string = '';
  357. public lock: boolean = false;
  358. public mid: number = 0;
  359. public data: any = null;
  360. /**接口成功回调 */
  361. public callback: Function | null = null;
  362. /**接口失败回调 */
  363. public failCallBack: Function | null = null;
  364. public time: number = 0;
  365. public sendNum: number = 0;
  366. public errorNum: number = 0;
  367. /**是否重复调用 */
  368. public isRepeat: boolean = false;
  369. public constructor(msg?: any) {
  370. this.time = Date.now();
  371. for (let key in msg) {
  372. let that = this as any
  373. that[key] = msg[key];
  374. }
  375. }
  376. };