HcSocket.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import website from '~src/config/index'
  2. import { getObjValue, isNullES } from 'js-fast-way'
  3. // 长链接推送插件
  4. class HcSocket {
  5. constructor(data, change, open) {
  6. this.limit = website.socketLimit
  7. this.interval = website.socketInterval
  8. this.param = getObjValue(data)
  9. this.onChange = change
  10. this.onSocketOpen = open
  11. this.socket = null
  12. this.isReconnecting = false
  13. this.connectionStatus = 'disconnected'
  14. this.isManualClosed = false
  15. if (this.validateParams()) {
  16. this.create()
  17. //this.handleMultipleTabs()
  18. }
  19. }
  20. validateParams() {
  21. const { projectId, contractId, userId } = this.param
  22. const { socket: socketUrl, clientId } = website
  23. return !(isNullES(socketUrl) || isNullES(clientId) || isNullES(projectId) || isNullES(contractId) || isNullES(userId))
  24. }
  25. //创建连接
  26. create() {
  27. const { projectId, contractId, userId } = this.param
  28. const { socket: socketUrl, clientId } = website
  29. const url = `${socketUrl}/${clientId}/${projectId}/${contractId}/${userId}`
  30. this.socket = new WebSocket(url)
  31. this.socket.onopen = this.handleOpen.bind(this)
  32. this.socket.onclose = this.handleClose.bind(this)
  33. this.socket.onmessage = this.handleMessage.bind(this)
  34. this.socket.onerror = this.handleError.bind(this)
  35. }
  36. handleOpen() {
  37. console.log('WebSocket 链接成功')
  38. this.connectionStatus = 'connected'
  39. this.isManualClosed = false
  40. if (typeof this.onSocketOpen === 'function' && this.onSocketOpen) {
  41. this.onSocketOpen()
  42. }
  43. }
  44. handleClose() {
  45. console.log('WebSocket 链接已断开')
  46. this.connectionStatus = 'disconnected'
  47. if (!this.isManualClosed) {
  48. this.reconnect()
  49. }
  50. }
  51. handleMessage({ data }) {
  52. try {
  53. const parsedData = JSON.parse(data)
  54. if (typeof this.onChange === 'function') {
  55. this.onChange(parsedData)
  56. }
  57. } catch (error) {
  58. console.error('解析 WebSocket 数据时出错:', error)
  59. }
  60. }
  61. handleError(error) {
  62. console.error('WebSocket 错误:', error)
  63. this.connectionStatus = 'error'
  64. }
  65. //发送消息
  66. send(data) {
  67. if (this.isSocket()) {
  68. this.socket.send(data)
  69. } else {
  70. console.warn('消息发送失败')
  71. }
  72. }
  73. //链接是否存在
  74. isSocket() {
  75. return !isNullES(this.socket) && (this.socket.readyState === WebSocket.OPEN)
  76. }
  77. //尝试重连
  78. async reconnect(attempts = 0) {
  79. if (this.isReconnecting || this.isManualClosed) return
  80. this.isReconnecting = true
  81. while (attempts < this.limit && !this.isSocket() && !this.isManualClosed) {
  82. console.log(`重新链接中... (${attempts + 1}/${this.limit})`)
  83. this.create()
  84. await new Promise(resolve => setTimeout(resolve, this.interval))
  85. attempts++
  86. }
  87. this.isReconnecting = false
  88. if (!this.isSocket() && !this.isManualClosed) {
  89. console.error('达到最大重连次数后仍然失败')
  90. }
  91. }
  92. handleMultipleTabs() {
  93. document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this))
  94. }
  95. // 处理多标签页问题
  96. handleVisibilityChange() {
  97. if (document.visibilityState === 'visible' && !this.isSocket() && !this.isManualClosed) {
  98. this.create()
  99. } else if (document.visibilityState === 'hidden') {
  100. this.close()
  101. }
  102. }
  103. //关闭或断开连接
  104. close() {
  105. this.isManualClosed = true
  106. if (this.isSocket()) {
  107. this.socket.close()
  108. }
  109. this.connectionStatus = 'disconnected'
  110. }
  111. destroy() {
  112. this.close()
  113. //document.removeEventListener('visibilitychange', this.handleVisibilityChange)
  114. this.socket = null
  115. this.onChange = null
  116. }
  117. }
  118. export { HcSocket }