websocketUtil.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  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 = 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. if (this.socketStatus < 10) {
  66. // 失败重连
  67. if (this.reconnectNum > 50) return;
  68. if (this.reconnectNum < this.reconnect_time.length) {
  69. reconnect_timeout = reconnect_time[this.reconnectNum]
  70. } else {
  71. reconnect_timeout = reconnect_time[this.reconnect_time.length - 1]
  72. }
  73. console.log("uniWebsocket 重新连接", this.socketStatus, this.reconnectNum, this.reconnect_timeout)
  74. this.reconnectNum = this.reconnectNum + 1
  75. this.reconnectTimeOut = setTimeout(() => {
  76. // 连接创建
  77. this.connectSocketInit();
  78. this.reconnect()
  79. }, reconnect_timeout)
  80. return;
  81. }
  82. console.log("uniWebsocket 自身巡检", socketStatus, reconnectNum, reconnect_timeout)
  83. // 自身巡检循环
  84. this.reconnectTimeOut = setTimeout(() => {
  85. // 连接创建
  86. this.connectSocketInit();
  87. this.reconnect()
  88. }, reconnect_timeout)
  89. //如果不是人为关闭的话,进行重连
  90. // if (!this.is_open_socket) {
  91. // this.reconnectTimeOut = setTimeout(() => {
  92. // this.connectSocketInit();
  93. // }, 3000)
  94. // }
  95. }
  96. generateSeq() {
  97. return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
  98. const r = Math.random() * 16 | 0;
  99. const v = c === 'x' ? r : (r & 0x3 | 0x8);
  100. return v.toString(16);
  101. });
  102. }
  103. // 进入这个页面的时候创建websocket连接【整个页面随时使用】
  104. connectSocketInit() {
  105. if (this.is_open_socket) {
  106. return null;
  107. }
  108. let that = this;
  109. this.socketTask = uni.connectSocket({
  110. url: this.url,
  111. success: () => {
  112. console.log("正准备建立websocket中...");
  113. // 返回实例
  114. return this.socketTask
  115. },
  116. });
  117. this.socketTask.onOpen((res) => {
  118. console.log("WebSocket连接正常!");
  119. clearTimeout(this.reconnectTimeOut)
  120. clearInterval(this.heartbeatInterval)
  121. this.is_open_socket = true;
  122. this.start();
  123. console.log("WebSocket连接正常!-start");
  124. // 注:只有连接正常打开中 ,才能正常收到消息
  125. this.socketTask.onMessage((res) => {
  126. let resdata = JSON.parse(res.data)
  127. //{"seq":"859a0fbd-05c5-4630-a160-e3cf284ad9c9","cmd":"login","response":{"code":200,"codeMsg":"{userId:'1',msg:'欢迎进入~'}","data":null}}
  128. console.log(resdata)
  129. if (resdata.cmd == "login") {
  130. if (resdata.response.codeMsg == "") {
  131. getApp().globalData.isLogin = 0;
  132. } else {
  133. getApp().globalData.isLogin = 1;
  134. console.log(resdata.response.codeMsg);
  135. getApp().globalData.userId = resdata.response.codeMsg;
  136. }
  137. uni.$emit('updateGroup', "") //重新加入群组,以便接收消息
  138. } else if (resdata.cmd == "msg") {
  139. uni.$emit('messageUpdate', resdata.response.data.msg)
  140. } else if (resdata.cmd == "heartbeat") {
  141. if (resdata.response.code == 1000) {
  142. that.toLogin();
  143. }
  144. }
  145. if (resdata.response.code != 200) {
  146. console.log(res.data)
  147. }
  148. });
  149. })
  150. // 监听连接失败,这里代码我注释掉的原因是因为如果服务器关闭后,和下面的onclose方法一起发起重连操作,这样会导致重复连接
  151. // uni.onSocketError((res) => {
  152. // console.log('WebSocket连接打开失败,请检查!');
  153. // this.is_open_socket = false;
  154. // this.reconnect();
  155. // });
  156. // 这里仅是事件监听【如果socket关闭了会执行】
  157. this.socketTask.onClose(() => {
  158. console.log("已经被关闭了")
  159. this.is_open_socket = false;
  160. this.reconnect();
  161. })
  162. }
  163. toLogin() {
  164. let that = this;
  165. that.send({
  166. seq: that.generateSeq(),
  167. cmd: "login",
  168. data: {
  169. "uuid": that.uuid,
  170. "appId": 101
  171. }
  172. });
  173. }
  174. //发送消息
  175. send(value) {
  176. console.log("send-content:", value);
  177. value.seq = this.generateSeq();
  178. // 注:只有连接正常打开中 ,才能正常成功发送消息
  179. let that = this;
  180. this.socketTask.send({
  181. data: JSON.stringify(value),
  182. async success() {
  183. // console.log("消息发送成功");
  184. },
  185. fail(e) {
  186. console.log("send-err:", e);
  187. // {"errMsg":"sendSocketMessage:fail WebSocket is not connected"} at common/websocketUtil.js:111
  188. if (e.errMsg.includes("fail WebSocket") || e.errMsg.includes("not connected")) {
  189. uni.closeSocket();
  190. that.reconnect();
  191. console.log('is now reconnect');
  192. // console.log(`"${str}" 包含 "${substr}"`);
  193. } else {
  194. console.log('errMsg', e.errMsg)
  195. // console.log(`"${str}" 不包含 "${substr}"`);
  196. }
  197. }
  198. });
  199. }
  200. //开启心跳检测
  201. start() {
  202. let that = this;
  203. if (this.heartbeatInterval != null) {
  204. clearInterval(this.heartbeatInterval);
  205. }
  206. console.log("WebSocket连接正常!-start2");
  207. that.send({
  208. seq: that.generateSeq(),
  209. cmd: "login",
  210. data: {
  211. "skey": that.uuid,
  212. "appId": 101
  213. }
  214. });
  215. this.heartbeatInterval = setInterval(() => {
  216. // console.log("heart",that.timeout);
  217. //{"seq":"1565336219141-266129","cmd":"login","data":{"userId":"马远","appId":101}}
  218. that.send({
  219. seq: that.generateSeq(),
  220. cmd: "heartbeat",
  221. data: {
  222. "userId": getApp().globalData.userId,
  223. "appId": 101
  224. }
  225. });
  226. }, that.timeout)
  227. }
  228. stop() {
  229. uni.closeSocket();
  230. }
  231. //外部获取消息
  232. getMessage(callback) {
  233. this.socketTask.onMessage((res) => {
  234. return callback(res)
  235. })
  236. }
  237. }
  238. module.exports = websocketUtil