websocketUtil.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. class websocketUtil {
  2. is_open_socket = false;
  3. socketStatus = 0 //避免重复连接 0 无连接 1-9连接中 10 已连接
  4. url = '';
  5. data = '';
  6. uuid = '';
  7. timeout = 10000;
  8. heartbeatInterval = null;
  9. reconnectTimeOut = null;
  10. reconnectNum = 0 //重连次数
  11. msgQueue = []
  12. socketTask = null //ws对象
  13. netIsConnected = false
  14. netType = 'none'
  15. autoFlag = true
  16. constructor(url, uuid) {
  17. this.is_open_socket = false; //避免重复连接
  18. this.url = url; //地址
  19. this.data = null;
  20. this.uuid = getApp().globalData.uuid;
  21. //心跳检测
  22. this.timeout = 10000;
  23. this.heartbeatInterval = null; //检测服务器端是否还活着
  24. this.reconnectTimeOut = null; //重连之后多久再次重连
  25. // 监听网络状态变化
  26. let that = this;
  27. uni.onNetworkStatusChange((res) => {
  28. console.log('WebSocket NetStatus', res.isConnected);
  29. console.log('WebSocket NetStatus', res.networkType);
  30. that.netIsConnected = res.isConnected
  31. that.netType = res.networkType
  32. that.reconnectNum = 0
  33. if (that.autoFlag) this.reconnect()
  34. });
  35. try {
  36. uni.getNetworkType({
  37. success: (res) => {
  38. console.log('WebSocket getNetworkType', res.networkType);
  39. that.netType = res.networkType;
  40. that.netIsConnected = true;
  41. that.reconnect();
  42. }
  43. });
  44. // 有return ,则构造方法返回return的对象,没有,则返回new的对象
  45. // return this.hhh
  46. } catch (e) {
  47. console.log('连接初始化失败', e);
  48. }
  49. // try {
  50. // return this.connectSocketInit()
  51. // } catch (e) {
  52. // console.log('catch');
  53. // this.is_open_socket = false
  54. // this.reconnect();
  55. // }
  56. }
  57. //重新连接
  58. reconnect() {
  59. // 失败重连频率
  60. const reconnect_time = [3000, 3000, 3000, 3000, 10000, 10000, 10000, 20000, 20000, 50000]
  61. // 自身巡检频率
  62. let reconnect_timeout = 30000
  63. //停止发送心跳
  64. // this.heartbeatInterval && clearInterval(this.heartbeatInterval)
  65. this.reconnectTimeOut && clearTimeout(this.reconnectTimeOut)
  66. if (this.socketStatus < 10) {
  67. // 失败重连
  68. if (this.reconnectNum > 50) return;
  69. if (this.reconnectNum < reconnect_time.length) {
  70. reconnect_timeout = reconnect_time[this.reconnectNum]
  71. } else {
  72. reconnect_timeout = reconnect_time[reconnect_time.length - 1]
  73. }
  74. console.log("uniWebsocket 重新连接", this.socketStatus, this.reconnectNum, reconnect_timeout)
  75. this.reconnectNum = this.reconnectNum + 1
  76. this.reconnectTimeOut = setTimeout(() => {
  77. // 连接创建
  78. this.connectSocketInit();
  79. this.reconnect()
  80. }, reconnect_timeout)
  81. return;
  82. }
  83. console.log("uniWebsocket 自身巡检", this.socketStatus, this.reconnectNum, reconnect_timeout)
  84. // 自身巡检循环
  85. this.reconnectTimeOut = setTimeout(() => {
  86. // 连接创建
  87. this.connectSocketInit();
  88. this.reconnect()
  89. }, reconnect_timeout)
  90. //如果不是人为关闭的话,进行重连
  91. // if (!this.is_open_socket) {
  92. // this.reconnectTimeOut = setTimeout(() => {
  93. // this.connectSocketInit();
  94. // }, 3000)
  95. // }
  96. }
  97. generateSeq() {
  98. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
  99. const r = Math.random() * 16 | 0;
  100. const v = c === 'x' ? r : (r & 0x3 | 0x8);
  101. return v.toString(16);
  102. });
  103. }
  104. // 进入这个页面的时候创建websocket连接【整个页面随时使用】
  105. connectSocketInit() {
  106. if (!this.netIsConnected || this.netType == 'none') return
  107. if (this.socketStatus > 0) return
  108. // if(!url) return
  109. // if (this.is_open_socket) {
  110. // return null;
  111. // }
  112. this.heartbeatInterval && clearInterval(this.heartbeatInterval)
  113. this.socketStatus = 1;
  114. uni.onSocketError(function(res) {
  115. that.socketStatus = 0;
  116. console.log('WebSocket 连接错误!', that.socketStatus, res);
  117. });
  118. let that = this;
  119. uni.onSocketClose(function(res) {
  120. that.socketStatus = 0;
  121. that.restart();
  122. console.log('WebSocket 连接关闭!', res);
  123. });
  124. uni.onSocketOpen(function(res) {
  125. that.socketStatus = 10;
  126. console.log('WebSocket 连接打开!', res);
  127. });
  128. this.socketTask = uni.connectSocket({
  129. url: that.url,
  130. success: () => {
  131. that.socketStatus = 2;
  132. console.log("正准备建立websocket中...");
  133. return that.socketTask;
  134. },
  135. fail: (data) => {
  136. that.socketStatus = 0;
  137. console.log("websocket 建立失败...");
  138. },
  139. complete: (data) => {
  140. that.socketStatus = 3;
  141. console.log("websocket 建立完成...");
  142. }
  143. });
  144. this.socketTask.onOpen((res) => {
  145. console.log("WebSocket连接正常!");
  146. // clearTimeout(this.reconnectTimeOut)
  147. // clearInterval(this.heartbeatInterval)
  148. that.socketStatus = 10;
  149. that.reconnectNum = 0;
  150. that.is_open_socket = true;
  151. that.start();
  152. console.log("WebSocket连接正常!-start");
  153. // 注:只有连接正常打开中 ,才能正常收到消息
  154. that.socketTask.onMessage((res) => {
  155. let resdata = JSON.parse(res.data)
  156. //{"seq":"859a0fbd-05c5-4630-a160-e3cf284ad9c9","cmd":"login","response":{"code":200,"codeMsg":"{userId:'1',msg:'欢迎进入~'}","data":null}}
  157. console.log(resdata)
  158. if (resdata.cmd == "login") {
  159. if (resdata.response.codeMsg == "") {
  160. getApp().globalData.isLogin = 0;
  161. } else {
  162. getApp().globalData.isLogin = 1;
  163. console.log(resdata.response.codeMsg);
  164. getApp().globalData.userId = resdata.response.codeMsg;
  165. }
  166. uni.$emit('updateGroup', "") //重新加入群组,以便接收消息
  167. } else if (resdata.cmd == "msg") {
  168. uni.$emit('messageUpdate', resdata.response.data.msg)
  169. } else if (resdata.cmd == "sendMsg") {
  170. uni.$emit('messageSend', resdata.response)
  171. } else if (resdata.cmd == "heartbeat") {
  172. if (resdata.response.code == 1000) {
  173. that.toLogin();
  174. }
  175. }
  176. if (resdata.response.code != 200) {
  177. // console.log(res.data)
  178. }
  179. });
  180. })
  181. // 监听连接失败,这里代码我注释掉的原因是因为如果服务器关闭后,和下面的onclose方法一起发起重连操作,这样会导致重复连接
  182. // uni.onSocketError((res) => {
  183. // console.log('WebSocket连接打开失败,请检查!');
  184. // this.is_open_socket = false;
  185. // this.reconnect();
  186. // });
  187. // 这里仅是事件监听【如果socket关闭了会执行】
  188. this.socketTask.onClose(() => {
  189. console.log("已经被关闭了")
  190. that.is_open_socket = false;
  191. that.reconnect();
  192. })
  193. }
  194. toLogin() {
  195. let that = this;
  196. that.send({
  197. seq: that.generateSeq(),
  198. cmd: "login",
  199. data: {
  200. "uuid": that.uuid,
  201. "appId": 101
  202. }
  203. });
  204. }
  205. //发送消息
  206. send(value) {
  207. value.seq = this.generateSeq();
  208. value = JSON.stringify(value)
  209. this.msgQueue.push(value);
  210. if (this.socketStatus < 10) {
  211. console.log("**********", "连接错误,消息发送失败", value);
  212. return;
  213. }
  214. let that = this;
  215. let msg = '';
  216. while (msg = this.msgQueue.shift()) {
  217. // 注:只有连接正常打开中 ,才能正常成功发送消息
  218. that.socketTask.send({
  219. data: msg,
  220. async success() {
  221. console.log('++++++++++', msg)
  222. // console.log("消息发送成功");
  223. },
  224. fail(e) {
  225. console.log("send-err:", e, msg);
  226. //errMsg sendSocketMessage:fail Error: SocketTask.readyState is not OPEN
  227. // {"errMsg":"sendSocketMessage:fail WebSocket is not connected"} at common/websocketUtil.js:111
  228. if (e.errMsg.includes("not OPEN") || e.errMsg.includes("fail WebSocket") || e.errMsg
  229. .includes("not connected")) {
  230. that.close()
  231. that.restart();
  232. console.log('is now reconnect');
  233. // console.log(`"${str}" 包含 "${substr}"`);
  234. } else {
  235. console.log('errMsg', e.errMsg)
  236. // console.log(`"${str}" 不包含 "${substr}"`);
  237. }
  238. }
  239. });
  240. }
  241. // 注:只有连接正常打开中 ,才能正常成功发送消息
  242. // let that = this;
  243. // this.socketTask.send({
  244. // data: JSON.stringify(value),
  245. // async success() {
  246. // // console.log("消息发送成功");
  247. // },
  248. // fail(e) {
  249. // console.log("send-err:", e);
  250. // // {"errMsg":"sendSocketMessage:fail WebSocket is not connected"} at common/websocketUtil.js:111
  251. // if (e.errMsg.includes("fail WebSocket") || e.errMsg.includes("not connected")) {
  252. // uni.closeSocket();
  253. // that.reconnect();
  254. // console.log('is now reconnect');
  255. // // console.log(`"${str}" 包含 "${substr}"`);
  256. // } else {
  257. // console.log('errMsg', e.errMsg)
  258. // // console.log(`"${str}" 不包含 "${substr}"`);
  259. // }
  260. // }
  261. // });
  262. }
  263. getStatus() {
  264. return this.socketStatus
  265. }
  266. //开启心跳检测
  267. start() {
  268. let that = this;
  269. if (this.heartbeatInterval != null) {
  270. clearInterval(this.heartbeatInterval);
  271. }
  272. console.log("WebSocket连接正常!-start2");
  273. that.send({
  274. seq: that.generateSeq(),
  275. cmd: "login",
  276. data: {
  277. "uuid": that.uuid,
  278. "appId": 101
  279. }
  280. });
  281. this.heartbeatInterval = setInterval(() => {
  282. // console.log("heart",that.timeout);
  283. //{"seq":"1565336219141-266129","cmd":"login","data":{"userId":"马远","appId":101}}
  284. if (that.socketStatus >= 10) {
  285. that.send({
  286. seq: that.generateSeq(),
  287. cmd: "heartbeat",
  288. data: {
  289. "userId": getApp().globalData.userId,
  290. "appId": 101
  291. }
  292. });
  293. }
  294. }, that.timeout)
  295. }
  296. /**
  297. * 重新打开链接
  298. */
  299. restart() {
  300. if (this.socketStatus >= 10) {
  301. console.log("连接已打开");
  302. return;
  303. }
  304. console.log("restart")
  305. this.autoFlag = true
  306. this.reconnect()
  307. }
  308. /**
  309. * 关闭链接
  310. */
  311. close() {
  312. console.log("关闭连接")
  313. if (this.socketStatus < 10) {
  314. console.log("连接未打开");
  315. return;
  316. }
  317. console.log("清理定时")
  318. // heartbeatTimeOut && clearTimeout(heartbeatTimeOut)
  319. this.heartbeatInterval && clearInterval(this.heartbeatInterval)
  320. this.reconnectTimeOut && clearTimeout(this.reconnectTimeOut)
  321. this.autoFlag = false
  322. this.socketStatus = 0;
  323. this.socketTask.close()
  324. console.log("正式关闭")
  325. }
  326. // stop() {
  327. // uni.closeSocket();
  328. // }
  329. //外部获取消息
  330. getMessage(callback) {
  331. console.log("message", this.socketTask);
  332. if (this.socketTask != null) {
  333. this.socketTask.onMessage((res) => {
  334. return callback(res)
  335. })
  336. }
  337. }
  338. }
  339. module.exports = websocketUtil