1. // socket连接
  2. import io from 'socket.io-client'
  3. import { getToken } from './utils'
  4. import { socketUrl, accessToken as accessTokenKey } from './config'
  5. /* connect status enum */
  6. const socketStatus = (function (status) {
  7. status[status['notconnect'] = 0] = 'notconnect'
  8. status[status['connecting'] = 1] = 'connecting'
  9. status[status['reconnecting'] = 2] = 'reconnecting'
  10. status[status['success'] = 3] = 'success'
  11. status[status['failed'] = -1] = 'failed'
  12. return status
  13. }({}))
  14. /* singleton socket object */
  15. const mySocket = (function () {
  16. /* const field */
  17. const SERVER_DISCONNECT = 'io server disconnect'
  18. const CLIENT_DISCONNECT = 'io client disconnect'
  19. const MAX_CONNECT_COUNT = 60
  20. function _mySocket() {
  21. this.connectCount = 0 // 定时重连的次数
  22. this._listeners = {}
  23. this.socket = null
  24. this.isClosed = false
  25. this.connectTimer = null
  26. this._initStatus()
  27. }
  28. _mySocket.prototype._initStatus = function () {
  29. let value = socketStatus.notconnect
  30. Object.defineProperty(_mySocket.prototype, 'status', {
  31. get: () => value,
  32. set: (newVal) => {
  33. if (newVal !== value) {
  34. value = newVal
  35. if (value === socketStatus.success) {
  36. this.connectCount = 0
  37. }
  38. this._dispatch('statusChange', value)
  39. }
  40. },
  41. enumerable: true,
  42. configurable: true
  43. })
  44. window.addEventListener('online', () => {
  45. this.reconnect()
  46. })
  47. }
  48. _mySocket.prototype.getStatus = function () {
  49. return this.status
  50. }
  51. _mySocket.prototype.connect = function () {
  52. if (!getToken()[accessTokenKey]) {
  53. return
  54. }
  55. this.isClosed = false
  56. this.socket = io(socketUrl, {
  57. reconnectionDelay: 50000
  58. })
  59. this._ListenerSocket()
  60. }
  61. /* 外部重连 */
  62. _mySocket.prototype.reconnect = function () {
  63. if (this.isClosed || this.status !== socketStatus.failed) { return }
  64. this.connectCount = 0
  65. this._reconnect(this.status, true)
  66. }
  67. /**
  68. * @param status socketStatus
  69. */
  70. _mySocket.prototype._reconnect = function (status, isManually = false) {
  71. if (this.isClosed) { return }
  72. if (this.connectCount > MAX_CONNECT_COUNT) {
  73. this.status = status
  74. return
  75. }
  76. this.status = socketStatus.reconnecting
  77. this.connectCount++
  78. let duration = isManually
  79. ? 0
  80. : (5 + this.connectCount < 10 ? 0 : Math.ceil(this.connectCount / 10)) * 1000
  81. if (this.connectTimer) {
  82. clearTimeout(this.connectTimer)
  83. }
  84. this.connectTimer = setTimeout(() => {
  85. this.socket.connect()
  86. }, duration)
  87. }
  88. _mySocket.prototype.on = function (type, fn, ctx = this) {
  89. if (!this._listeners[type]) {
  90. this._listeners[type] = []
  91. }
  92. this._listeners[type].push([fn, ctx])
  93. }
  94. _mySocket.prototype.close = function () {
  95. console.log('socket2 🔊:', 'close')
  96. this.isClosed = true
  97. this.status = socketStatus.notconnect
  98. if (this.connectTimer) {
  99. clearTimeout(this.connectTimer)
  100. this.connectTimer = null
  101. }
  102. this.socket.close()
  103. }
  104. _mySocket.prototype.destroy = function (removeListerner = true) {
  105. if (!this.isClosed) {
  106. this.close()
  107. }
  108. if (removeListerner) {
  109. this._listeners = {}
  110. }
  111. this.socket && this.socket.destroy()
  112. this.socket = null
  113. }
  114. _mySocket.prototype._dispatch = function (type) {
  115. let events = this._listeners[type]
  116. if (!events) { return }
  117. let len = events.length
  118. let copyEvents = [...events]
  119. for (let index = 0; index < len; index++) {
  120. const event = copyEvents[index]
  121. let [fn, ctx] = event
  122. if (fn) {
  123. fn.apply(ctx, [].slice.call(arguments, 1))
  124. }
  125. }
  126. }
  127. _mySocket.prototype._login = function () {
  128. const jsonObject = {
  129. messageType: 'L01',
  130. accessToken: getToken()[accessTokenKey],
  131. sourceId: 'pc',
  132. body: '消息主体'
  133. }
  134. this.socket.emit('loginEvent', JSON.stringify(jsonObject))
  135. }
  136. _mySocket.prototype._ListenerSocket = function () {
  137. // 连接中
  138. this.socket.on('connecting', () => {
  139. console.log('socket2 🔊:', 'connecting')
  140. this.status = socketStatus.connecting
  141. })
  142. // 连接成功
  143. this.socket.on('connect', () => {
  144. console.log('socket2 🔊:', 'connect')
  145. this.status = socketStatus.success
  146. this._login()
  147. })
  148. // 连接错误
  149. this.socket.on('connect_error', (err) => {
  150. console.log('socket2 🔊:', 'connect_error')
  151. this._reconnect(socketStatus.failed)
  152. })
  153. // 连接超时
  154. this.socket.on('connect_timeout', () => {
  155. console.log('socket2 🔊:', 'connect_timeout')
  156. this._reconnect(socketStatus.failed)
  157. })
  158. /* =============== custom event ================ */
  159. this.socket.on('loginSuccess', () => {
  160. console.log('socket2 🔊:', 'socket登录成功')
  161. })
  162. // 弹出效果
  163. this.socket.on('weather', data => {
  164. let thisWeather = JSON.stringify(data)
  165. if (thisWeather != this._prevWeather) {
  166. this._prevWeather = thisWeather
  167. this._dispatch('weather', data)
  168. }
  169. })
  170. // 消息推送
  171. this.socket.on('messageStats', data => {
  172. this._dispatch('messageStats', data)
  173. })
  174. // 邮件事件
  175. this.socket.on('mailEvent', data => {
  176. console.log('邮件事件')
  177. this._dispatch('mailEvent', data)
  178. })
  179. // 踢掉
  180. this.socket.on('offsiteLogin', data => {
  181. console.log('socket2 🔊:', '被踢掉:offsiteLogin')
  182. // this.status = socketStatus.notconnect
  183. this.close()
  184. // 退出登陆
  185. this._dispatch('offsiteLogin')
  186. })
  187. /* =============== custom event end ================ */
  188. // 重连中
  189. this.socket.on('reconnecting', () => {
  190. console.log('socket2 🔊:', 'reconnecting')
  191. this.status = socketStatus.reconnecting
  192. })
  193. // 重连成功
  194. this.socket.on('reconnect', () => {
  195. console.log('socket2 🔊:', 'reconnect')
  196. this.status = socketStatus.success
  197. })
  198. // 重连出错
  199. this.socket.on('reconnect_error', () => {
  200. console.log('socket2 🔊:', 'reconnect_error')
  201. this._reconnect(socketStatus.failed)
  202. })
  203. // 重连失败
  204. this.socket.on('reconnect_failed', () => {
  205. console.log('socket2 🔊:', 'reconnect_failed')
  206. this._reconnect(socketStatus.failed)
  207. })
  208. // 断开
  209. this.socket.on('disconnect', reason => {
  210. console.log('socket2 🔊:', `disconnect:reason==>${reason}`)
  211. if (reason === CLIENT_DISCONNECT) {
  212. this.socket.close()
  213. return
  214. }
  215. if (reason === SERVER_DISCONNECT) {
  216. this._reconnect(socketStatus.failed)
  217. return
  218. }
  219. this._reconnect(socketStatus.failed)
  220. })
  221. // 连接错误
  222. this.socket.on('error', (err) => {
  223. console.log('socket2 🔊:', 'error')
  224. this._reconnect(socketStatus.failed)
  225. })
  226. }
  227. return new _mySocket()
  228. }())
  229. export {
  230. socketStatus,
  231. mySocket
  232. }

socket.io-client库

image.png